1 // Copyright (c) 2012 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.
5 #ifndef CHROME_BROWSER_CHROMEOS_IMAGEBURNER_BURN_MANAGER_H_
6 #define CHROME_BROWSER_CHROMEOS_IMAGEBURNER_BURN_MANAGER_H_
14 #include "base/files/file_path.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/observer_list.h"
17 #include "base/time.h"
18 #include "chrome/browser/chromeos/cros/burn_library.h"
19 #include "chrome/browser/chromeos/cros/network_library.h"
20 #include "chrome/browser/chromeos/imageburner/burn_device_handler.h"
21 #include "chromeos/disks/disk_mount_manager.h"
22 #include "googleurl/src/gurl.h"
23 #include "net/url_request/url_fetcher_delegate.h"
30 namespace imageburner
{
32 // Config file properties.
33 extern const char kName
[];
34 extern const char kHwid
[];
35 extern const char kFileName
[];
36 extern const char kUrl
[];
38 // Config file is divided into blocks. Each block is associated with one image
39 // and containes information about that image in form of key-value pairs, one
40 // pair per line. Each block starts with name property.
41 // Also, Each image can be associated with multiple hardware classes, so we
42 // treat hwid property separately.
43 // Config file example:
56 explicit ConfigFile(const std::string
& file_content
);
60 // Builds config file data structure.
61 void reset(const std::string
& file_content
);
65 bool empty() const { return config_struct_
.empty(); }
67 size_t size() const { return config_struct_
.size(); }
69 // Returns property_name property of image for hardware class hwid.
70 const std::string
& GetProperty(const std::string
& property_name
,
71 const std::string
& hwid
) const;
74 void DeleteLastBlockIfHasNoHwid();
75 void ProcessLine(const std::vector
<std::string
>& line
);
77 typedef std::map
<std::string
, std::string
> PropertyMap
;
78 typedef std::set
<std::string
> HwidsSet
;
80 // Struct that contains config file block info. We separate hwid from other
81 // properties for two reasons:
82 // * there are multiple hwids defined for each block.
83 // * we will retieve properties by hwid.
84 struct ConfigFileBlock
{
88 PropertyMap properties
;
92 // At the moment we have only two entries in the config file, so we can live
93 // with linear search. Should consider changing data structure if number of
94 // entries gets bigger.
95 // Also, there is only one entry for each hwid, if that changes we should
96 // return vector of strings.
97 typedef std::list
<ConfigFileBlock
> BlockList
;
98 BlockList config_struct_
;
109 State
state() { return state_
; }
113 virtual void OnBurnStateChanged(State new_state
) = 0;
114 virtual void OnError(int error_message_id
) = 0;
120 bool download_started() const { return download_started_
; }
121 void OnDownloadStarted() {
122 download_started_
= true;
123 state_
= DOWNLOADING
;
127 bool download_finished() const { return download_finished_
; }
128 void OnDownloadFinished() { download_finished_
= true; }
130 void OnBurnStarted() {
135 bool new_burn_posible() const { return state_
== INITIAL
; }
138 void OnError(int error_message_id
);
140 void OnStateChanged() {
141 FOR_EACH_OBSERVER(Observer
, observers_
, OnBurnStateChanged(state_
));
144 void AddObserver(Observer
* observer
) {
145 observers_
.AddObserver(observer
);
148 void RemoveObserver(Observer
* observer
) {
149 observers_
.RemoveObserver(observer
);
153 bool download_started_
;
154 bool download_finished_
;
158 ObserverList
<Observer
> observers_
;
160 DISALLOW_COPY_AND_ASSIGN(StateMachine
);
163 // This is a system-wide singleton class to manage burning the recovery media.
164 // Here is how the burning image procedure works:
165 // 0) Choose the device the image to be burned (manually via web-ui).
166 // 1) Create ImageDir, which is a working directory for the procedure.
167 // 2) Download the config file.
168 // 2-1) Fetch the config file from the server.
169 // 2-2) Parse the config file content, and extract url and name of the image
171 // 3) Fetch the image file.
172 // 4) Burn the image to the device.
173 // 4-1) Unzip the fetched image file.
174 // 4-2) Unmount the device from file system.
175 // 4-3) Copy the unzipped file to the device directly.
176 // Currently, this only provides some methods to start/cancel background tasks,
177 // and some accessors to obtain the current status. Other functions are
178 // distributed among BurnController and BurnLibrary.
179 // TODO(hidehiko): Simplify the relationship among this class, BurnLibrary,
180 // BurnController and helper classes defined above.
181 class BurnManager
: public net::URLFetcherDelegate
,
182 public BurnLibrary::Observer
,
183 public NetworkLibrary::NetworkManagerObserver
{
186 // Interface for classes that need to observe events for the burning image
190 // Triggered when a burnable device is added.
191 virtual void OnDeviceAdded(const disks::DiskMountManager::Disk
& disk
) = 0;
193 // Triggered when a burnable device is removed.
194 virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk
& disk
) = 0;
196 // Triggered when a network is detected.
197 virtual void OnNetworkDetected() = 0;
199 // Triggered when the creating a ImageDir is done.
200 // The status of the creating the directory is passed to |success|.
201 virtual void OnImageDirCreated(bool success
) = 0;
203 // Triggered when the fetching of the config file is done.
204 // The result status of the fetch is passed to |success|.
205 virtual void OnConfigFileFetched(bool success
) = 0;
207 // Triggered during the image file downloading periodically.
208 // |estimated_remaining_time| is the remaining duration to download the
209 // remaining content estimated based on the elapsed time.
210 virtual void OnImageFileFetchDownloadProgressUpdated(
211 int64 received_bytes
,
213 const base::TimeDelta
& estimated_remaining_time
) = 0;
215 // Triggered when the fetching of the image file is done.
216 // The result status is passed to |success|.
217 virtual void OnImageFileFetched(bool success
) = 0;
219 // Triggered during the burning the image to the device.
220 // See also BurnLibrary's comment for more details.
221 virtual void OnBurnProgressUpdated(BurnEvent event
,
222 const ImageBurnStatus
& status
) = 0;
225 // Creates the global BurnManager instance.
226 static void Initialize();
228 // Destroys the global BurnManager instance if it exists.
229 static void Shutdown();
231 // Returns the global BurnManager instance.
232 // Initialize() should already have been called.
233 static BurnManager
* GetInstance();
236 void AddObserver(Observer
* observer
);
238 // Remove an observer.
239 void RemoveObserver(Observer
* observer
);
241 // Returns devices on which we can burn recovery image.
242 std::vector
<disks::DiskMountManager::Disk
> GetBurnableDevices();
244 // Returns true if some network is connected.
245 bool IsNetworkConnected() const;
247 // Cancels a currently running task of burning recovery image.
248 // Note: currently we only support Cancel method, which may look asymmetry
249 // because there is no method to start the task. It is just because that
250 // we are on the way of refactoring.
251 // TODO(hidehiko): Introduce Start method, which actually starts a whole
252 // image burning task, including config/image file fetching and unzipping.
255 // Error is usually detected by all existing Burn handlers, but only first
256 // one that calls this method should actually process it.
257 // The |message_id| is the id for human readable error message, although
258 // here is not the place to handle UI.
259 // TODO(hidehiko): Replace it with semantical enum value.
260 // Note: currently, due to some implementation reasons, the errors can be
261 // observed in outside classes, and this method is public to be accessed from
263 // TODO(hidehiko): Refactor the structure.
264 void OnError(int message_id
);
266 // Creates URL image should be fetched from.
267 // Must be called from UI thread.
268 void FetchConfigFile();
270 // Fetch a zipped recovery image.
273 // Burns the image of |zip_image_file_path_| and |image_file_name|
274 // to |target_device_path_| and |target_file_path_|.
275 // TODO(hidehiko): The name "Burn" sounds confusing because there are two
277 // 1) In wider sense, Burn means a whole process, including config/image
278 // file fetching, or file unzipping.
279 // 2) In narrower sense, Burn means just write the image onto a device.
280 // To avoid such a confusion, rename the method.
283 // Cancels the image burning.
284 // TODO(hidehiko): Rename this method along with the renaming of DoBurn.
285 void CancelBurnImage();
287 // Cancel fetching image.
288 void CancelImageFetch();
290 // URLFetcherDelegate overrides:
291 virtual void OnURLFetchComplete(const net::URLFetcher
* source
) OVERRIDE
;
292 virtual void OnURLFetchDownloadProgress(const net::URLFetcher
* source
,
294 int64 total
) OVERRIDE
;
296 // BurnLibrary::Observer orverrides.
297 virtual void BurnProgressUpdated(BurnLibrary
* object
,
299 const ImageBurnStatus
& status
) OVERRIDE
;
301 // NetworkLibrary::NetworkManagerObserver interface.
302 virtual void OnNetworkManagerChanged(NetworkLibrary
* obj
) OVERRIDE
;
304 // Creates directory image will be downloaded to.
305 // Must be called from FILE thread.
306 void CreateImageDir();
308 // Returns directory image should be dopwnloaded to.
309 // The directory has to be previously created.
310 const base::FilePath
& GetImageDir();
312 const base::FilePath
& target_device_path() { return target_device_path_
; }
313 void set_target_device_path(const base::FilePath
& path
) {
314 target_device_path_
= path
;
317 const base::FilePath
& target_file_path() { return target_file_path_
; }
318 void set_target_file_path(const base::FilePath
& path
) {
319 target_file_path_
= path
;
322 void ResetTargetPaths() {
323 target_device_path_
.clear();
324 target_file_path_
.clear();
327 StateMachine
* state_machine() const { return state_machine_
.get(); }
331 virtual ~BurnManager();
333 void OnImageDirCreated(bool success
);
334 void ConfigFileFetched(bool fetched
, const std::string
& content
);
336 void NotifyDeviceAdded(const disks::DiskMountManager::Disk
& disk
);
337 void NotifyDeviceRemoved(const disks::DiskMountManager::Disk
& disk
);
339 BurnDeviceHandler device_handler_
;
341 base::FilePath image_dir_
;
342 base::FilePath zip_image_file_path_
;
343 base::FilePath target_device_path_
;
344 base::FilePath target_file_path_
;
346 GURL config_file_url_
;
347 bool config_file_fetched_
;
348 std::string image_file_name_
;
349 GURL image_download_url_
;
351 scoped_ptr
<StateMachine
> state_machine_
;
353 scoped_ptr
<net::URLFetcher
> config_fetcher_
;
354 scoped_ptr
<net::URLFetcher
> image_fetcher_
;
356 base::TimeTicks tick_image_download_start_
;
357 int64 bytes_image_download_progress_last_reported_
;
359 ObserverList
<Observer
> observers_
;
361 // Note: This should remain the last member so it'll be destroyed and
362 // invalidate its weak pointers before any other members are destroyed.
363 base::WeakPtrFactory
<BurnManager
> weak_ptr_factory_
;
365 DISALLOW_COPY_AND_ASSIGN(BurnManager
);
368 } // namespace imageburner
370 } // namespace chromeos
372 #endif // CHROME_BROWSER_CHROMEOS_IMAGEBURNER_BURN_MANAGER_H_