1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros/burn_library.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <cstring>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/linked_ptr.h"
9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chromeos/cros/cros_library.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace chromeos {
13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass BurnLibraryImpl : public BurnLibrary,
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                        public base::SupportsWeakPtr<BurnLibraryImpl> {
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  BurnLibraryImpl();
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~BurnLibraryImpl();
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // BurnLibrary implementation.
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void AddObserver(Observer* observer);
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void RemoveObserver(Observer* observer);
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path);
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool BurnImage(const FilePath& from_path, const FilePath& to_path);
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void UpdateBurnStatus(const ImageBurnStatus& status, BurnEventType evt);
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void Init();
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static void BurnStatusChangedHandler(void* object,
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       const BurnStatus& status,
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                       BurnEventType evt);
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ObserverList<BurnLibrary::Observer> observers_;
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  BurnStatusConnection burn_status_connection_;
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Holds a path that is currently being burnt to.
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string target_path_;
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(BurnLibraryImpl);
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass BurnLibraryTaskProxy
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : public base::RefCountedThreadSafe<BurnLibraryTaskProxy> {
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public:
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  explicit BurnLibraryTaskProxy(const base::WeakPtr<BurnLibraryImpl>& library);
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void BurnImage(const FilePath& from_path, const FilePath& to_path);
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void UpdateBurnStatus(ImageBurnStatus* status, BurnEventType evt);
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::WeakPtr<BurnLibraryImpl> library_;
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  friend class base::RefCountedThreadSafe<BurnLibraryTaskProxy>;
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(BurnLibraryTaskProxy);
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen};
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBurnLibraryImpl::BurnLibraryImpl() {
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (CrosLibrary::Get()->EnsureLoaded()) {
64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      Init();
65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    } else {
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      LOG(ERROR) << "Cros Library has not been loaded";
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBurnLibraryImpl::~BurnLibraryImpl() {
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (burn_status_connection_) {
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    DisconnectBurnStatus(burn_status_connection_);
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryImpl::AddObserver(Observer* observer) {
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  observers_.AddObserver(observer);
78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryImpl::RemoveObserver(Observer* observer) {
81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  observers_.RemoveObserver(observer);
82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BurnLibraryImpl::DoBurn(const FilePath& from_path,
85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                             const FilePath& to_path) {
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  BurnLibraryTaskProxy* task = new BurnLibraryTaskProxy(AsWeakPtr());
87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  task->AddRef();
88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  task->BurnImage(from_path, to_path);
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NewRunnableMethod(task, &BurnLibraryTaskProxy::BurnImage,
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        from_path, to_path));
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BurnLibraryImpl::BurnImage(const FilePath& from_path,
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                const FilePath& to_path) {
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Make sure we run on file thread.
98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Check if there is a target path already being burnt to.
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (target_path_ == "") {
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    target_path_ = to_path.value();
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  } else {
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  StartBurn(from_path.value().c_str(), to_path.value().c_str(),
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen            burn_status_connection_);
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryImpl::BurnStatusChangedHandler(void* object,
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                               const BurnStatus& status,
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                               BurnEventType evt) {
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  BurnLibraryImpl* burn = static_cast<BurnLibraryImpl*>(object);
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Copy burn status because it will be freed after returning from this method.
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  ImageBurnStatus* status_copy = new ImageBurnStatus(status);
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  BurnLibraryTaskProxy* task = new BurnLibraryTaskProxy(burn->AsWeakPtr());
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  task->AddRef();
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      NewRunnableMethod(task, &BurnLibraryTaskProxy::UpdateBurnStatus,
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        status_copy, evt));
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryImpl::Init() {
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  burn_status_connection_ = MonitorBurnStatus(&BurnStatusChangedHandler, this);
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryImpl::UpdateBurnStatus(const ImageBurnStatus& status,
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                       BurnEventType evt) {
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Make sure we run on UI thread.
134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // If burn is finished, remove target paths from paths being burnt to.
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // This has to be done in thread-safe way, hence using task proxy class.
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if ((evt == BURN_CANCELED || evt == BURN_COMPLETE) &&
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      target_path_ == status.target_path)
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    target_path_ = "";
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  FOR_EACH_OBSERVER(Observer, observers_, ProgressUpdated(this, evt, status));
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBurnLibraryTaskProxy::BurnLibraryTaskProxy(
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                        const base::WeakPtr<BurnLibraryImpl>& library)
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                            : library_(library) {
148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryTaskProxy::BurnImage(const FilePath& from_path,
151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                     const FilePath& to_path) {
152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  library_->BurnImage(from_path, to_path);
153bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
154bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BurnLibraryTaskProxy::UpdateBurnStatus(ImageBurnStatus* status,
156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                            BurnEventType evt) {
157bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  library_->UpdateBurnStatus(*status, evt);
158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  delete status;
159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass BurnLibraryStubImpl : public BurnLibrary {
163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public:
164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  BurnLibraryStubImpl() {}
165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  virtual ~BurnLibraryStubImpl() {}
166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
167bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // BurnLibrary overrides.
168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  virtual void AddObserver(Observer* observer) {}
169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  virtual void RemoveObserver(Observer* observer) {}
170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  virtual bool DoBurn(const FilePath& from_path, const FilePath& to_path) {
171bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
172bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
173bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
174bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(BurnLibraryStubImpl);
175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen};
176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
177bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static
178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBurnLibrary* BurnLibrary::GetImpl(bool stub) {
179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (stub)
180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return new BurnLibraryStubImpl();
181bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  else
182bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return new BurnLibraryImpl();
183bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}  // namespace chromeos
186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Allows InvokeLater without adding refcounting. This class is a Singleton and
188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// won't be deleted until it's last InvokeLater is run.
189bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::BurnLibraryImpl);
190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
191