15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/update_engine_client.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/command_line.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/message_loop/message_loop.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chromeos/chromeos_switches.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/bus.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_proxy.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kReleaseChannelDev[] = "dev-channel";
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kReleaseChannelBeta[] = "beta-channel";
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kReleaseChannelStable[] = "stable-channel";
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Delay between successive state transitions during AU.
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kStateTransitionDefaultDelayMs = 3000;
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Delay between successive notifications about downloading progress
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// during fake AU.
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kStateTransitionDownloadingDelayMs = 250;
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Size of parts of a "new" image which are downloaded each
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// |kStateTransitionDownloadingDelayMs| during fake AU.
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int64_t kDownloadSizeDelta = 1 << 19;
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns UPDATE_STATUS_ERROR on error.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& str) {
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  VLOG(1) << "UpdateStatusFromString got " << str << " as input.";
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusIdle)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_IDLE;
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusCheckingForUpdate)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusUpdateAvailable)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusDownloading)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusVerifying)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_VERIFYING;
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusFinalizing)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_FINALIZING;
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusUpdatedNeedReboot)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (str == update_engine::kUpdateStatusReportingErrorEvent)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (str == update_engine::kUpdateStatusAttemptingRollback)
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UpdateEngineClient::UPDATE_STATUS_ERROR;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used in UpdateEngineClient::EmptyUpdateCheckCallback().
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EmptyUpdateCheckCallbackBody(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateEngineClient::UpdateCheckResult unused_result) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool IsValidChannel(const std::string& channel) {
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return channel == kReleaseChannelDev ||
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      channel == kReleaseChannelBeta ||
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      channel == kReleaseChannelStable;
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The UpdateEngineClient implementation used in production.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UpdateEngineClientImpl : public UpdateEngineClient {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  UpdateEngineClientImpl()
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      : update_engine_proxy_(NULL), last_status_(), weak_ptr_factory_(this) {}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~UpdateEngineClientImpl() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UpdateEngineClient implementation:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.AddObserver(observer);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observers_.RemoveObserver(observer);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observers_.HasObserver(observer);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestUpdateCheck(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const UpdateCheckCallback& callback) OVERRIDE {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_engine::kUpdateEngineInterface,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_engine::kAttemptUpdate);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageWriter writer(&method_call);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendString("");  // Unused.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    writer.AppendString("");  // Unused.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requesting an update check";
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    update_engine_proxy_->CallMethod(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   callback));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RebootAfterUpdate() OVERRIDE {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MethodCall method_call(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_engine::kUpdateEngineInterface,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        update_engine::kRebootIfNeeded);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Requesting a reboot";
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    update_engine_proxy_->CallMethod(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &method_call,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void Rollback() OVERRIDE {
130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Requesting a rollback";
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch     dbus::MethodCall method_call(
132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        update_engine::kUpdateEngineInterface,
133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        update_engine::kAttemptRollback);
134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    dbus::MessageWriter writer(&method_call);
135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    writer.AppendBool(true /* powerwash */);
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    update_engine_proxy_->CallMethod(
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        &method_call,
139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&UpdateEngineClientImpl::OnRollback,
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void CanRollbackCheck(
146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const RollbackCheckCallback& callback) OVERRIDE {
147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    dbus::MethodCall method_call(
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        update_engine::kUpdateEngineInterface,
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        update_engine::kCanRollback);
150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Requesting to get rollback availability status";
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    update_engine_proxy_->CallMethod(
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        &method_call,
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&UpdateEngineClientImpl::OnCanRollbackCheck,
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   callback));
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status GetLastStatus() OVERRIDE {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return last_status_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void SetChannel(const std::string& target_channel,
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          bool is_powerwash_allowed) OVERRIDE {
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!IsValidChannel(target_channel)) {
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(ERROR) << "Invalid channel name: " << target_channel;
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dbus::MethodCall method_call(
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        update_engine::kUpdateEngineInterface,
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        update_engine::kSetChannel);
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dbus::MessageWriter writer(&method_call);
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendString(target_channel);
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendBool(is_powerwash_allowed);
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VLOG(1) << "Requesting to set channel: "
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            << "target_channel=" << target_channel << ", "
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            << "is_powerwash_allowed=" << is_powerwash_allowed;
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    update_engine_proxy_->CallMethod(
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        &method_call,
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::Bind(&UpdateEngineClientImpl::OnSetChannel,
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void GetChannel(bool get_current_channel,
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          const GetChannelCallback& callback) OVERRIDE {
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dbus::MethodCall method_call(
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        update_engine::kUpdateEngineInterface,
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        update_engine::kGetChannel);
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dbus::MessageWriter writer(&method_call);
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writer.AppendBool(get_current_channel);
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VLOG(1) << "Requesting to get channel, get_current_channel="
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            << get_current_channel;
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    update_engine_proxy_->CallMethod(
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        &method_call,
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::Bind(&UpdateEngineClientImpl::OnGetChannel,
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   weak_ptr_factory_.GetWeakPtr(),
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   callback));
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) protected:
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {
208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    update_engine_proxy_ = bus->GetObjectProxy(
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        update_engine::kUpdateEngineServiceName,
210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        dbus::ObjectPath(update_engine::kUpdateEngineServicePath));
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Monitor the D-Bus signal for brightness changes. Only the power
213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // manager knows the actual brightness level. We don't cache the
214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // brightness level in Chrome as it will make things less reliable.
215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    update_engine_proxy_->ConnectToSignal(
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        update_engine::kUpdateEngineInterface,
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        update_engine::kStatusUpdate,
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected,
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Get update engine status for the initial status. Update engine won't
224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // send StatusUpdate signal unless there is a status change. If chrome
225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set,
226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // restarted chrome would not get this status. See crbug.com/154104.
227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    GetUpdateEngineStatus();
228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetUpdateEngineStatus() {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MethodCall method_call(
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        update_engine::kUpdateEngineInterface,
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        update_engine::kGetStatus);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    update_engine_proxy_->CallMethodWithErrorCallback(
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &method_call,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::OnGetStatus,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&UpdateEngineClientImpl::OnGetStatusError,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a response for RequestUpdateCheck() is received.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnRequestUpdateCheck(const UpdateCheckCallback& callback,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            dbus::Response* response) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to request update check";
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(UPDATE_RESULT_FAILED);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(UPDATE_RESULT_SUCCESS);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a response for RebootAfterUpdate() is received.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnRebootAfterUpdate(dbus::Response* response) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!response) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Failed to request rebooting after update";
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Called when a response for Rollback() is received.
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void OnRollback(dbus::Response* response) {
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (!response) {
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      LOG(ERROR) << "Failed to rollback";
267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return;
268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Called when a response for CanRollbackCheck() is received.
272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  void OnCanRollbackCheck(const RollbackCheckCallback& callback,
273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          dbus::Response* response) {
274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (!response) {
275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      LOG(ERROR) << "Failed to request rollback availability status";
276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      callback.Run(false);
277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return;
278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    dbus::MessageReader reader(response);
280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool can_rollback;
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (!reader.PopBool(&can_rollback)) {
282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      LOG(ERROR) << "Incorrect response: " << response->ToString();
283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      callback.Run(false);
284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return;
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Rollback availability status received: " << can_rollback;
287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    callback.Run(can_rollback);
288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called when a response for GetStatus is received.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGetStatus(dbus::Response* response) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!response) {
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Failed to get response for GetStatus request.";
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(response);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string current_operation;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!(reader.PopInt64(&status.last_checked_time) &&
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reader.PopDouble(&status.download_progress) &&
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reader.PopString(&current_operation) &&
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reader.PopString(&status.new_version) &&
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reader.PopInt64(&status.new_size))) {
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "GetStatus had incorrect response: "
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << response->ToString();
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status.status = UpdateStatusFromString(current_operation);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_status_ = status;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called when GetStatus call failed.
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnGetStatusError(dbus::ErrorResponse* error) {
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(ERROR) << "GetStatus request failed with error: "
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << (error ? error->ToString() : "");
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Called when a response for SetReleaseChannel() is received.
321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  void OnSetChannel(dbus::Response* response) {
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!response) {
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(ERROR) << "Failed to request setting channel";
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VLOG(1) << "Succeeded to set channel";
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Called when a response for GetChannel() is received.
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void OnGetChannel(const GetChannelCallback& callback,
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    dbus::Response* response) {
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!response) {
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(ERROR) << "Failed to request getting channel";
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.Run("");
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dbus::MessageReader reader(response);
338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string channel;
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!reader.PopString(&channel)) {
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(ERROR) << "Incorrect response: " << response->ToString();
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.Run("");
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return;
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VLOG(1) << "The channel received: " << channel;
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    callback.Run(channel);
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when a status update signal is received.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StatusUpdateReceived(dbus::Signal* signal) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Status update signal received: " << signal->ToString();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::MessageReader reader(signal);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 last_checked_time = 0;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double progress = 0.0;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string current_operation;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string new_version;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t new_size = 0;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(reader.PopInt64(&last_checked_time) &&
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopDouble(&progress) &&
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopString(&current_operation) &&
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopString(&new_version) &&
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reader.PopInt64(&new_size))) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Status changed signal had incorrect parameters: "
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << signal->ToString();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status status;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status.last_checked_time = last_checked_time;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status.download_progress = progress;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status.status = UpdateStatusFromString(current_operation);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status.new_version = new_version;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status.new_size = new_size;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_status_ = status;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when the status update signal is initially connected.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StatusUpdateConnected(const std::string& interface_name,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const std::string& signal_name,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             bool success) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, !success)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to connect to status updated signal.";
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectProxy* update_engine_proxy_;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Status last_status_;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The UpdateEngineClient implementation used on Linux desktop,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which does nothing.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UpdateEngineClientStubImpl : public UpdateEngineClient {
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  UpdateEngineClientStubImpl()
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : current_channel_(kReleaseChannelBeta),
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        target_channel_(kReleaseChannelBeta) {}
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // UpdateEngineClient implementation:
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void Init(dbus::Bus* bus) OVERRIDE {}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE { return false; }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestUpdateCheck(
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const UpdateCheckCallback& callback) OVERRIDE {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RebootAfterUpdate() OVERRIDE {}
415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void Rollback() OVERRIDE {}
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void CanRollbackCheck(
417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const RollbackCheckCallback& callback) OVERRIDE {
418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    callback.Run(true);
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status GetLastStatus() OVERRIDE { return Status(); }
421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void SetChannel(const std::string& target_channel,
422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          bool is_powerwash_allowed) OVERRIDE {
423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Requesting to set channel: "
424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            << "target_channel=" << target_channel << ", "
425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            << "is_powerwash_allowed=" << is_powerwash_allowed;
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    target_channel_ = target_channel;
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void GetChannel(bool get_current_channel,
429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          const GetChannelCallback& callback) OVERRIDE {
430effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    VLOG(1) << "Requesting to get channel, get_current_channel="
431effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch            << get_current_channel;
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (get_current_channel)
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback.Run(current_channel_);
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback.Run(target_channel_);
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string current_channel_;
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string target_channel_;
4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The UpdateEngineClient implementation used on Linux desktop, which
4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// tries to emulate real update engine client.
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class UpdateEngineClientFakeImpl : public UpdateEngineClientStubImpl {
4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public:
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UpdateEngineClientFakeImpl() : weak_factory_(this) {
4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual ~UpdateEngineClientFakeImpl() {
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // UpdateEngineClient implementation:
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
4541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (observer)
4551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      observers_.AddObserver(observer);
4561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (observer)
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      observers_.RemoveObserver(observer);
4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
4641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return observers_.HasObserver(observer);
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void RequestUpdateCheck(
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const UpdateCheckCallback& callback) OVERRIDE {
4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (last_status_.status != UPDATE_STATUS_IDLE) {
4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      callback.Run(UPDATE_RESULT_FAILED);
4711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return;
4721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    callback.Run(UPDATE_RESULT_SUCCESS);
4741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
4751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    last_status_.download_progress = 0.0;
4761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    last_status_.last_checked_time = 0;
4771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    last_status_.new_size = 0;
4781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
4791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        FROM_HERE,
4801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
4811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   weak_factory_.GetWeakPtr()),
4821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kStateTransitionDefaultDelayMs));
4831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
4841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual Status GetLastStatus() OVERRIDE { return last_status_; }
4861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private:
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void StateTransition() {
4891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    UpdateStatusOperation next_status = UPDATE_STATUS_ERROR;
4901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int delay_ms = kStateTransitionDefaultDelayMs;
4911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    switch (last_status_.status) {
4921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_ERROR:
4931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_IDLE:
4941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_UPDATED_NEED_REBOOT:
4951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_REPORTING_ERROR_EVENT:
49646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      case UPDATE_STATUS_ATTEMPTING_ROLLBACK:
4971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return;
4981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_CHECKING_FOR_UPDATE:
4991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        next_status = UPDATE_STATUS_UPDATE_AVAILABLE;
5001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
5011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_UPDATE_AVAILABLE:
5021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        next_status = UPDATE_STATUS_DOWNLOADING;
5031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
5041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_DOWNLOADING:
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        if (last_status_.download_progress >= 1.0) {
5061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          next_status = UPDATE_STATUS_VERIFYING;
5071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        } else {
5081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          next_status = UPDATE_STATUS_DOWNLOADING;
5091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          last_status_.download_progress += 0.01;
5101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          last_status_.new_size = kDownloadSizeDelta;
5111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          delay_ms = kStateTransitionDownloadingDelayMs;
5121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        }
5131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
5141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_VERIFYING:
5151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        next_status = UPDATE_STATUS_FINALIZING;
5161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
5171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case UPDATE_STATUS_FINALIZING:
5181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        next_status = UPDATE_STATUS_IDLE;
5191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        break;
5201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    last_status_.status = next_status;
5221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(last_status_));
5231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (last_status_.status != UPDATE_STATUS_IDLE) {
5241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      base::MessageLoop::current()->PostDelayedTask(
5251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          FROM_HERE,
5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
5271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                     weak_factory_.GetWeakPtr()),
5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          base::TimeDelta::FromMilliseconds(delay_ms));
5291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ObserverList<Observer> observers_;
5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  Status last_status_;
5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  base::WeakPtrFactory<UpdateEngineClientFakeImpl> weak_factory_;
5361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientFakeImpl);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient::UpdateEngineClient() {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient::~UpdateEngineClient() {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient::UpdateCheckCallback
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient::EmptyUpdateCheckCallback() {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::Bind(&EmptyUpdateCheckCallbackBody);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateEngineClient* UpdateEngineClient::Create(
554424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DBusClientImplementationType type) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return new UpdateEngineClientImpl();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
5581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestAutoUpdateUI))
5591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return new UpdateEngineClientFakeImpl();
5601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  else
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return new UpdateEngineClientStubImpl();
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
565