普通文本  |  156行  |  4.29 KB

// 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);