// 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/cros/update_library.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
#include "content/common/notification_type.h"
namespace chromeos {
class UpdateLibraryImpl : public UpdateLibrary {
public:
UpdateLibraryImpl()
: status_connection_(NULL) {
if (CrosLibrary::Get()->EnsureLoaded()) {
Init();
}
}
~UpdateLibraryImpl() {
if (status_connection_) {
DisconnectUpdateProgress(status_connection_);
}
}
void AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
bool HasObserver(Observer* observer) {
return observers_.HasObserver(observer);
}
void RequestUpdateCheck(chromeos::UpdateCallback callback, void* user_data) {
if (CrosLibrary::Get()->EnsureLoaded())
chromeos::RequestUpdateCheck(callback, user_data);
}
bool RebootAfterUpdate() {
if (!CrosLibrary::Get()->EnsureLoaded())
return false;
return RebootIfUpdated();
}
void SetReleaseTrack(const std::string& track) {
if (CrosLibrary::Get()->EnsureLoaded())
chromeos::SetUpdateTrack(track);
}
void GetReleaseTrack(chromeos::UpdateTrackCallback callback,
void* user_data) {
if (CrosLibrary::Get()->EnsureLoaded())
chromeos::RequestUpdateTrack(callback, user_data);
}
const UpdateLibrary::Status& status() const {
return status_;
}
private:
static void ChangedHandler(void* object,
const UpdateProgress& status) {
UpdateLibraryImpl* updater = static_cast<UpdateLibraryImpl*>(object);
updater->UpdateStatus(Status(status));
}
void Init() {
status_connection_ = MonitorUpdateStatus(&ChangedHandler, this);
}
void UpdateStatus(const Status& status) {
// Make sure we run on UI thread.
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
NewRunnableMethod(this, &UpdateLibraryImpl::UpdateStatus, status));
return;
}
status_ = status;
FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(this));
// If the update is ready to install, send a notification so that Chrome
// can update the UI.
if (status_.status == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
NotificationService::current()->Notify(
NotificationType::UPGRADE_RECOMMENDED,
Source<UpdateLibrary>(this),
NotificationService::NoDetails());
}
}
ObserverList<Observer> observers_;
// A reference to the update api, to allow callbacks when the update
// status changes.
UpdateStatusConnection status_connection_;
// The latest power status.
Status status_;
DISALLOW_COPY_AND_ASSIGN(UpdateLibraryImpl);
};
class UpdateLibraryStubImpl : public UpdateLibrary {
public:
UpdateLibraryStubImpl() {}
~UpdateLibraryStubImpl() {}
void AddObserver(Observer* observer) {}
void RemoveObserver(Observer* observer) {}
bool HasObserver(Observer* observer) { return false; }
void RequestUpdateCheck(chromeos::UpdateCallback callback, void* user_data) {
if (callback)
callback(user_data, UPDATE_RESULT_FAILED, "stub update");
}
bool RebootAfterUpdate() { return false; }
void SetReleaseTrack(const std::string& track) { }
void GetReleaseTrack(chromeos::UpdateTrackCallback callback,
void* user_data) {
if (callback)
callback(user_data, "beta-channel");
}
const UpdateLibrary::Status& status() const {
return status_;
}
private:
Status status_;
DISALLOW_COPY_AND_ASSIGN(UpdateLibraryStubImpl);
};
// static
UpdateLibrary* UpdateLibrary::GetImpl(bool stub) {
if (stub)
return new UpdateLibraryStubImpl();
else
return new UpdateLibraryImpl();
}
} // namespace chromeos
// Allows InvokeLater without adding refcounting. This class is a Singleton and
// won't be deleted until it's last InvokeLater is run.
DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::UpdateLibraryImpl);