Home | History | Annotate | Download | only in cros
      1 // Copyright (c) 2011 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.
      4 
      5 #include "chrome/browser/chromeos/cros/burn_library.h"
      6 
      7 #include <cstring>
      8 #include "base/memory/linked_ptr.h"
      9 #include "chrome/browser/chromeos/cros/cros_library.h"
     10 #include "content/browser/browser_thread.h"
     11 
     12 namespace chromeos {
     13 
     14 class BurnLibraryImpl : public BurnLibrary,
     15                         public base::SupportsWeakPtr<BurnLibraryImpl> {
     16  public:
     17 
     18   BurnLibraryImpl();
     19   virtual ~BurnLibraryImpl();
     20 
     21   // BurnLibrary implementation.
     22   virtual void AddObserver(Observer* observer);
     23   virtual void RemoveObserver(Observer* observer);
     24   virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path);
     25 
     26   bool BurnImage(const FilePath& from_path, const FilePath& to_path);
     27   void UpdateBurnStatus(const ImageBurnStatus& status, BurnEventType evt);
     28 
     29  private:
     30   void Init();
     31   static void BurnStatusChangedHandler(void* object,
     32                                        const BurnStatus& status,
     33                                        BurnEventType evt);
     34 
     35  private:
     36   ObserverList<BurnLibrary::Observer> observers_;
     37   BurnStatusConnection burn_status_connection_;
     38 
     39   // Holds a path that is currently being burnt to.
     40   std::string target_path_;
     41 
     42   DISALLOW_COPY_AND_ASSIGN(BurnLibraryImpl);
     43 };
     44 
     45 class BurnLibraryTaskProxy
     46     : public base::RefCountedThreadSafe<BurnLibraryTaskProxy> {
     47  public:
     48   explicit BurnLibraryTaskProxy(const base::WeakPtr<BurnLibraryImpl>& library);
     49 
     50   void BurnImage(const FilePath& from_path, const FilePath& to_path);
     51 
     52   void UpdateBurnStatus(ImageBurnStatus* status, BurnEventType evt);
     53 
     54  private:
     55   base::WeakPtr<BurnLibraryImpl> library_;
     56 
     57   friend class base::RefCountedThreadSafe<BurnLibraryTaskProxy>;
     58 
     59   DISALLOW_COPY_AND_ASSIGN(BurnLibraryTaskProxy);
     60 };
     61 
     62 BurnLibraryImpl::BurnLibraryImpl() {
     63   if (CrosLibrary::Get()->EnsureLoaded()) {
     64       Init();
     65     } else {
     66       LOG(ERROR) << "Cros Library has not been loaded";
     67     }
     68 }
     69 
     70 BurnLibraryImpl::~BurnLibraryImpl() {
     71   if (burn_status_connection_) {
     72     DisconnectBurnStatus(burn_status_connection_);
     73   }
     74 }
     75 
     76 void BurnLibraryImpl::AddObserver(Observer* observer) {
     77   observers_.AddObserver(observer);
     78 }
     79 
     80 void BurnLibraryImpl::RemoveObserver(Observer* observer) {
     81   observers_.RemoveObserver(observer);
     82 }
     83 
     84 bool BurnLibraryImpl::DoBurn(const FilePath& from_path,
     85                              const FilePath& to_path) {
     86   BurnLibraryTaskProxy* task = new BurnLibraryTaskProxy(AsWeakPtr());
     87   task->AddRef();
     88   task->BurnImage(from_path, to_path);
     89   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
     90       NewRunnableMethod(task, &BurnLibraryTaskProxy::BurnImage,
     91                         from_path, to_path));
     92   return true;
     93 }
     94 
     95 bool BurnLibraryImpl::BurnImage(const FilePath& from_path,
     96                                 const FilePath& to_path) {
     97   // Make sure we run on file thread.
     98   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
     99 
    100   // Check if there is a target path already being burnt to.
    101   if (target_path_ == "") {
    102     target_path_ = to_path.value();
    103   } else {
    104     return false;
    105   }
    106 
    107   StartBurn(from_path.value().c_str(), to_path.value().c_str(),
    108             burn_status_connection_);
    109   return true;
    110 }
    111 
    112 void BurnLibraryImpl::BurnStatusChangedHandler(void* object,
    113                                                const BurnStatus& status,
    114                                                BurnEventType evt) {
    115   BurnLibraryImpl* burn = static_cast<BurnLibraryImpl*>(object);
    116 
    117   // Copy burn status because it will be freed after returning from this method.
    118   ImageBurnStatus* status_copy = new ImageBurnStatus(status);
    119 
    120   BurnLibraryTaskProxy* task = new BurnLibraryTaskProxy(burn->AsWeakPtr());
    121   task->AddRef();
    122   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    123       NewRunnableMethod(task, &BurnLibraryTaskProxy::UpdateBurnStatus,
    124                         status_copy, evt));
    125 }
    126 
    127 void BurnLibraryImpl::Init() {
    128   burn_status_connection_ = MonitorBurnStatus(&BurnStatusChangedHandler, this);
    129 }
    130 
    131 void BurnLibraryImpl::UpdateBurnStatus(const ImageBurnStatus& status,
    132                                        BurnEventType evt) {
    133   // Make sure we run on UI thread.
    134   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    135 
    136   // If burn is finished, remove target paths from paths being burnt to.
    137   // This has to be done in thread-safe way, hence using task proxy class.
    138   if ((evt == BURN_CANCELED || evt == BURN_COMPLETE) &&
    139       target_path_ == status.target_path)
    140     target_path_ = "";
    141 
    142   FOR_EACH_OBSERVER(Observer, observers_, ProgressUpdated(this, evt, status));
    143 }
    144 
    145 BurnLibraryTaskProxy::BurnLibraryTaskProxy(
    146                         const base::WeakPtr<BurnLibraryImpl>& library)
    147                             : library_(library) {
    148 }
    149 
    150 void BurnLibraryTaskProxy::BurnImage(const FilePath& from_path,
    151                                      const FilePath& to_path) {
    152   library_->BurnImage(from_path, to_path);
    153 }
    154 
    155 void BurnLibraryTaskProxy::UpdateBurnStatus(ImageBurnStatus* status,
    156                                             BurnEventType evt) {
    157   library_->UpdateBurnStatus(*status, evt);
    158   delete status;
    159 }
    160 
    161 
    162 class BurnLibraryStubImpl : public BurnLibrary {
    163  public:
    164   BurnLibraryStubImpl() {}
    165   virtual ~BurnLibraryStubImpl() {}
    166 
    167   // BurnLibrary overrides.
    168   virtual void AddObserver(Observer* observer) {}
    169   virtual void RemoveObserver(Observer* observer) {}
    170   virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path) {
    171     return false;
    172   }
    173 
    174   DISALLOW_COPY_AND_ASSIGN(BurnLibraryStubImpl);
    175 };
    176 
    177 // static
    178 BurnLibrary* BurnLibrary::GetImpl(bool stub) {
    179   if (stub)
    180     return new BurnLibraryStubImpl();
    181   else
    182     return new BurnLibraryImpl();
    183 }
    184 
    185 }  // namespace chromeos
    186 
    187 // Allows InvokeLater without adding refcounting. This class is a Singleton and
    188 // won't be deleted until it's last InvokeLater is run.
    189 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::BurnLibraryImpl);
    190 
    191