• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BurnLibraryImpl()62 BurnLibraryImpl::BurnLibraryImpl() {
63   if (CrosLibrary::Get()->EnsureLoaded()) {
64       Init();
65     } else {
66       LOG(ERROR) << "Cros Library has not been loaded";
67     }
68 }
69 
~BurnLibraryImpl()70 BurnLibraryImpl::~BurnLibraryImpl() {
71   if (burn_status_connection_) {
72     DisconnectBurnStatus(burn_status_connection_);
73   }
74 }
75 
AddObserver(Observer * observer)76 void BurnLibraryImpl::AddObserver(Observer* observer) {
77   observers_.AddObserver(observer);
78 }
79 
RemoveObserver(Observer * observer)80 void BurnLibraryImpl::RemoveObserver(Observer* observer) {
81   observers_.RemoveObserver(observer);
82 }
83 
DoBurn(const FilePath & from_path,const FilePath & to_path)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 
BurnImage(const FilePath & from_path,const FilePath & to_path)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 
BurnStatusChangedHandler(void * object,const BurnStatus & status,BurnEventType evt)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 
Init()127 void BurnLibraryImpl::Init() {
128   burn_status_connection_ = MonitorBurnStatus(&BurnStatusChangedHandler, this);
129 }
130 
UpdateBurnStatus(const ImageBurnStatus & status,BurnEventType evt)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 
BurnLibraryTaskProxy(const base::WeakPtr<BurnLibraryImpl> & library)145 BurnLibraryTaskProxy::BurnLibraryTaskProxy(
146                         const base::WeakPtr<BurnLibraryImpl>& library)
147                             : library_(library) {
148 }
149 
BurnImage(const FilePath & from_path,const FilePath & to_path)150 void BurnLibraryTaskProxy::BurnImage(const FilePath& from_path,
151                                      const FilePath& to_path) {
152   library_->BurnImage(from_path, to_path);
153 }
154 
UpdateBurnStatus(ImageBurnStatus * status,BurnEventType evt)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:
BurnLibraryStubImpl()164   BurnLibraryStubImpl() {}
~BurnLibraryStubImpl()165   virtual ~BurnLibraryStubImpl() {}
166 
167   // BurnLibrary overrides.
AddObserver(Observer * observer)168   virtual void AddObserver(Observer* observer) {}
RemoveObserver(Observer * observer)169   virtual void RemoveObserver(Observer* observer) {}
DoBurn(const FilePath & from_path,const FilePath & to_path)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
GetImpl(bool stub)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