diff options
-rw-r--r-- | chrome/browser/chromeos/dbus/mock_update_engine_client.cc | 13 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/mock_update_engine_client.h | 32 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/update_engine_client.cc | 289 | ||||
-rw-r--r-- | chrome/browser/chromeos/dbus/update_engine_client.h | 122 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 2 |
6 files changed, 460 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/dbus/mock_update_engine_client.cc b/chrome/browser/chromeos/dbus/mock_update_engine_client.cc new file mode 100644 index 0000000..93379d4 --- /dev/null +++ b/chrome/browser/chromeos/dbus/mock_update_engine_client.cc @@ -0,0 +1,13 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/dbus/mock_update_engine_client.h" + +namespace chromeos { + +MockUpdateEngineClient::MockUpdateEngineClient() {} + +MockUpdateEngineClient::~MockUpdateEngineClient() {} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/dbus/mock_update_engine_client.h b/chrome/browser/chromeos/dbus/mock_update_engine_client.h new file mode 100644 index 0000000..21d6f4e --- /dev/null +++ b/chrome/browser/chromeos/dbus/mock_update_engine_client.h @@ -0,0 +1,32 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ +#define CHROME_BROWSER_CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ + +#include <string> + +#include "chrome/browser/chromeos/dbus/update_engine_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockUpdateEngineClient : public UpdateEngineClient { + public: + MockUpdateEngineClient(); + virtual ~MockUpdateEngineClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(HasObserver, bool(Observer*)); + MOCK_METHOD1(RequestUpdateCheck, void(UpdateCheckCallback)); + MOCK_METHOD0(RebootAfterUpdate, void()); + MOCK_METHOD1(SetReleaseTrack, void(const std::string&)); + MOCK_METHOD1(GetReleaseTrack, void(GetReleaseTrackCallback)); + MOCK_METHOD0(GetLastStatus, Status()); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ diff --git a/chrome/browser/chromeos/dbus/update_engine_client.cc b/chrome/browser/chromeos/dbus/update_engine_client.cc new file mode 100644 index 0000000..ed5cecb --- /dev/null +++ b/chrome/browser/chromeos/dbus/update_engine_client.cc @@ -0,0 +1,289 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/dbus/update_engine_client.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/string_util.h" +#include "chrome/browser/chromeos/system/runtime_environment.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { +namespace { + +// Returns UPDATE_STATUS_ERROR on error. +UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString( + const std::string& str) { + if (str == "UPDATE_STATUS_IDLE") + return UpdateEngineClient::UPDATE_STATUS_IDLE; + if (str == "UPDATE_STATUS_CHECKING_FOR_UPDATE") + return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE; + if (str == "UPDATE_STATUS_UPDATE_AVAILABLE") + return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE; + if (str == "UPDATE_STATUS_DOWNLOADING") + return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING; + if (str == "UPDATE_STATUS_VERIFYING") + return UpdateEngineClient::UPDATE_STATUS_VERIFYING; + if (str == "UPDATE_STATUS_FINALIZING") + return UpdateEngineClient::UPDATE_STATUS_FINALIZING; + if (str == "UPDATE_STATUS_UPDATED_NEED_REBOOT") + return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT; + if (str == "UPDATE_STATUS_REPORTING_ERROR_EVENT") + return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT; + return UpdateEngineClient::UPDATE_STATUS_ERROR; +} + +// Used in UpdateEngineClient::EmptyUpdateCheckCallback(). +void EmptyUpdateCheckCallbackBody( + UpdateEngineClient::UpdateCheckResult unused_result) { +} + +} // namespace + +// The UpdateEngineClient implementation used in production. +class UpdateEngineClientImpl : public UpdateEngineClient { + public: + explicit UpdateEngineClientImpl(dbus::Bus* bus) + : update_engine_proxy_(NULL), + weak_ptr_factory_(this), + last_status_() { + update_engine_proxy_ = bus->GetObjectProxy( + update_engine::kUpdateEngineServiceName, + update_engine::kUpdateEngineServicePath); + + // Monitor the D-Bus signal for brightness changes. Only the power + // manager knows the actual brightness level. We don't cache the + // brightness level in Chrome as it will make things less reliable. + update_engine_proxy_->ConnectToSignal( + update_engine::kUpdateEngineInterface, + update_engine::kStatusUpdate, + base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~UpdateEngineClientImpl() { + } + + // UpdateEngineClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + // UpdateEngineClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + // UpdateEngineClient override. + virtual bool HasObserver(Observer* observer) OVERRIDE { + return observers_.HasObserver(observer); + } + + // UpdateEngineClient override. + virtual void RequestUpdateCheck(UpdateCheckCallback callback) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kAttemptUpdate); + dbus::MessageWriter writer(&method_call); + writer.AppendString(""); // Unused. + writer.AppendString(""); // Unused. + + VLOG(1) << "Requesting an update check"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // UpdateEngineClient override. + virtual void RebootAfterUpdate() OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kRebootIfNeeded); + + VLOG(1) << "Requesting a reboot"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate, + weak_ptr_factory_.GetWeakPtr())); + } + + // UpdateEngineClient override. + virtual void SetReleaseTrack(const std::string& track) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kSetTrack); + dbus::MessageWriter writer(&method_call); + writer.AppendString(track); + + VLOG(1) << "Requesting to set the release track to " << track; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnSetReleaseTrack, + weak_ptr_factory_.GetWeakPtr())); + } + + // UpdateEngineClient override. + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kGetTrack); + + VLOG(1) << "Requesting to get the current release track"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnGetReleaseTrack, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // UpdateEngineClient override. + virtual Status GetLastStatus() OVERRIDE { + return last_status_; + } + + private: + // Called when a response for RequestUpdateCheck() is received. + void OnRequestUpdateCheck(UpdateCheckCallback callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request update check"; + callback.Run(UPDATE_RESULT_FAILED); + return; + } + callback.Run(UPDATE_RESULT_SUCCESS); + } + + // Called when a response for RebootAfterUpdate() is received. + void OnRebootAfterUpdate(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request rebooting after update"; + return; + } + } + + // Called when a response for SetReleaseTrack() is received. + void OnSetReleaseTrack(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request setting release track"; + return; + } + } + + // Called when a response for GetReleaseTrack() is received. + void OnGetReleaseTrack(GetReleaseTrackCallback callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request getting release track"; + callback.Run(""); + return; + } + dbus::MessageReader reader(response); + std::string release_track; + if (!reader.PopString(&release_track)) { + LOG(ERROR) << "Incorrect response: " << response->ToString(); + callback.Run(""); + return; + } + VLOG(1) << "The current release track received: " << release_track; + callback.Run(release_track); + } + + // Called when a status update signal is received. + void StatusUpdateReceived(dbus::Signal* signal) { + VLOG(1) << "Status update signal received: " << signal->ToString(); + dbus::MessageReader reader(signal); + int64 last_checked_time = 0; + double progress = 0.0; + std::string current_operation; + std::string new_version; + int64_t new_size = 0; + if (!(reader.PopInt64(&last_checked_time) && + reader.PopDouble(&progress) && + reader.PopString(¤t_operation) && + reader.PopString(&new_version) && + reader.PopInt64(&new_size))) { + LOG(ERROR) << "Status changed signal had incorrect parameters: " + << signal->ToString(); + return; + } + Status status; + status.last_checked_time = last_checked_time; + status.download_progress = progress; + status.status = UpdateStatusFromString(current_operation); + status.new_version = new_version; + status.new_size = new_size; + + last_status_ = status; + FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status)); + } + + // Called when the status update signal is initially connected. + void StatusUpdateConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) + << "Failed to connect to status updated signal."; + } + + dbus::ObjectProxy* update_engine_proxy_; + ObserverList<Observer> observers_; + base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_; + Status last_status_; + + DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl); +}; + +// The UpdateEngineClient implementation used on Linux desktop, +// which does nothing. +class UpdateEngineClientStubImpl : public UpdateEngineClient { + // UpdateEngineClient overrides. + virtual void AddObserver(Observer* observer) OVERRIDE {} + virtual void RemoveObserver(Observer* observer) OVERRIDE {} + virtual bool HasObserver(Observer* observer) OVERRIDE { return false; } + + virtual void RequestUpdateCheck(UpdateCheckCallback callback) OVERRIDE { + callback.Run(UPDATE_RESULT_FAILED); + } + virtual void RebootAfterUpdate() OVERRIDE {} + virtual void SetReleaseTrack(const std::string& track) OVERRIDE {} + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) OVERRIDE { + callback.Run("beta-channel"); + } + virtual Status GetLastStatus() OVERRIDE { return Status(); } +}; + +UpdateEngineClient::UpdateEngineClient() { +} + +UpdateEngineClient::~UpdateEngineClient() { +} + +// static +UpdateEngineClient::UpdateCheckCallback +UpdateEngineClient::EmptyUpdateCheckCallback() { + return base::Bind(&EmptyUpdateCheckCallbackBody); +} + +// static +UpdateEngineClient* UpdateEngineClient::Create(dbus::Bus* bus) { + if (system::runtime_environment::IsRunningOnChromeOS()) { + return new UpdateEngineClientImpl(bus); + } else { + return new UpdateEngineClientStubImpl(); + } +} + +} // namespace chromeos diff --git a/chrome/browser/chromeos/dbus/update_engine_client.h b/chrome/browser/chromeos/dbus/update_engine_client.h new file mode 100644 index 0000000..52d5d20 --- /dev/null +++ b/chrome/browser/chromeos/dbus/update_engine_client.h @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ +#define CHROME_BROWSER_CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ + +#include "base/callback.h" +#include "base/observer_list.h" + +#include <string> + +namespace dbus { +class Bus; +} // namespace + +namespace chromeos { + +// UpdateEngineClient is used to communicate with the update engine. +class UpdateEngineClient { + public: + // Edges for state machine + // IDLE->CHECKING_FOR_UPDATE + // CHECKING_FOR_UPDATE->IDLE + // CHECKING_FOR_UPDATE->UPDATE_AVAILABLE + // ... + // FINALIZING->UPDATE_NEED_REBOOT + // Any state can transition to REPORTING_ERROR_EVENT and then on to IDLE. + enum UpdateStatusOperation { + UPDATE_STATUS_ERROR = -1, + UPDATE_STATUS_IDLE = 0, + UPDATE_STATUS_CHECKING_FOR_UPDATE, + UPDATE_STATUS_UPDATE_AVAILABLE, + UPDATE_STATUS_DOWNLOADING, + UPDATE_STATUS_VERIFYING, + UPDATE_STATUS_FINALIZING, + UPDATE_STATUS_UPDATED_NEED_REBOOT, + UPDATE_STATUS_REPORTING_ERROR_EVENT + }; + + // The status of the ongoing update attempt. + struct Status { + Status() : status(UPDATE_STATUS_IDLE), + download_progress(0.0), + last_checked_time(0), + new_size(0) { + } + + UpdateStatusOperation status; + double download_progress; // 0.0 - 1.0 + int64_t last_checked_time; // As reported by std::time(). + std::string new_version; + int64_t new_size; // Valid during DOWNLOADING, in bytes. + }; + + // The result code used for RequestUpdateCheck(). + enum UpdateCheckResult { + UPDATE_RESULT_SUCCESS, + UPDATE_RESULT_FAILED, + }; + + // Interface for observing changes from the update engine. + class Observer { + public: + // Called when the status is updated. + virtual void UpdateStatusChanged(const Status& status) {} + }; + + virtual ~UpdateEngineClient(); + + // Adds and removes the observer. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + // Returns true if this object has the given observer. + virtual bool HasObserver(Observer* observer) = 0; + + // Called once RequestUpdateCheck() is complete. Takes one parameter: + // - UpdateCheckResult: the result of the update check. + typedef base::Callback<void(UpdateCheckResult)> UpdateCheckCallback; + + // Requests an update check and calls |callback| when completed. + virtual void RequestUpdateCheck(UpdateCheckCallback callback) = 0; + + // Reboots if update has been performed. + virtual void RebootAfterUpdate() = 0; + + // Requests to set the release track (channel). |track| should look like + // "beta-channel" or "dev-channel". + virtual void SetReleaseTrack(const std::string& track) = 0; + + // Called once GetReleaseTrack() is complete. Takes one parameter; + // - string: the release track name like "beta-channel". + typedef base::Callback<void(const std::string&)> GetReleaseTrackCallback; + + // Requests to get the release track and calls |callback| with the + // release track (channel). On error, calls |callback| with an empty + // string. + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) = 0; + + // Returns the last status the object received from the update engine. + // + // Ideally, the D-Bus client should be state-less, but there are clients + // that need this information. + virtual Status GetLastStatus() = 0; + + // Returns an empty UpdateCheckCallback that does nothing. + static UpdateCheckCallback EmptyUpdateCheckCallback(); + + // Creates the instance. + static UpdateEngineClient* Create(dbus::Bus* bus); + + protected: + // Create() should be used instead. + UpdateEngineClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(UpdateEngineClient); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a2be100..481689d 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -450,6 +450,8 @@ 'browser/chromeos/dbus/session_manager_client.h', 'browser/chromeos/dbus/speech_synthesizer_client.cc', 'browser/chromeos/dbus/speech_synthesizer_client.h', + 'browser/chromeos/dbus/update_engine_client.cc', + 'browser/chromeos/dbus/update_engine_client.h', 'browser/chromeos/disks/disk_mount_manager.cc', 'browser/chromeos/disks/disk_mount_manager.h', 'browser/chromeos/drop_shadow_label.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index a9b1b8fb..004d649 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -110,6 +110,8 @@ 'browser/chromeos/dbus/mock_session_manager_client.h', 'browser/chromeos/dbus/mock_speech_synthesizer_client.cc', 'browser/chromeos/dbus/mock_speech_synthesizer_client.h', + 'browser/chromeos/dbus/mock_update_engine_client.cc', + 'browser/chromeos/dbus/mock_update_engine_client.h', 'browser/chromeos/login/mock_signed_settings_helper.cc', 'browser/chromeos/login/mock_signed_settings_helper.h', # The only thing used from browser is Browser::Type. |