Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / chromeos / imageburner / burn_manager.h
blob23cf6629ea1402d819818ba34d208818b629d97b
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_
8 #include <list>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
14 #include "base/files/file_path.h"
15 #include "base/memory/ref_counted_memory.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/observer_list.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/chromeos/imageburner/burn_device_handler.h"
20 #include "chromeos/disks/disk_mount_manager.h"
21 #include "chromeos/network/network_state_handler_observer.h"
22 #include "net/url_request/url_fetcher_delegate.h"
23 #include "url/gurl.h"
25 namespace net {
26 class URLFetcher;
27 class URLRequestContextGetter;
28 } // namespace net
30 namespace chromeos {
32 enum BurnEvent {
33 UNZIP_STARTED,
34 UNZIP_COMPLETE,
35 UNZIP_FAIL,
36 BURN_UPDATE,
37 BURN_SUCCESS,
38 BURN_FAIL,
39 UNKNOWN
42 struct ImageBurnStatus {
43 ImageBurnStatus() : amount_burnt(0), total_size(0) {
46 ImageBurnStatus(int64 burnt, int64 total)
47 : amount_burnt(burnt), total_size(total) {
50 int64 amount_burnt;
51 int64 total_size;
54 namespace imageburner {
56 // An enum used to describe what type of progress is being made.
57 // TODO(hidehiko): This should be merged into the StateMachine's state.
58 enum ProgressType {
59 DOWNLOADING,
60 UNZIPPING,
61 BURNING
64 // Config file properties.
65 extern const char kName[];
66 extern const char kHwid[];
67 extern const char kFileName[];
68 extern const char kUrl[];
70 // Config file is divided into blocks. Each block is associated with one image
71 // and containes information about that image in form of key-value pairs, one
72 // pair per line. Each block starts with name property.
73 // Also, Each image can be associated with multiple hardware classes, so we
74 // treat hwid property separately.
75 // Config file example:
76 // name=image1
77 // version=version1
78 // hwid=hwid1
79 // hwid=hwid2
81 // name=name2
82 // version=version2
83 // hwid=hwid3
84 class ConfigFile {
85 public:
86 ConfigFile();
88 explicit ConfigFile(const std::string& file_content);
90 ~ConfigFile();
92 // Builds config file data structure.
93 void reset(const std::string& file_content);
95 void clear();
97 bool empty() const { return config_struct_.empty(); }
99 size_t size() const { return config_struct_.size(); }
101 // Returns property_name property of image for hardware class hwid.
102 const std::string& GetProperty(const std::string& property_name,
103 const std::string& hwid) const;
105 private:
106 void DeleteLastBlockIfHasNoHwid();
107 void ProcessLine(const std::vector<std::string>& line);
109 typedef std::map<std::string, std::string> PropertyMap;
110 typedef std::set<std::string> HwidsSet;
112 // Struct that contains config file block info. We separate hwid from other
113 // properties for two reasons:
114 // * there are multiple hwids defined for each block.
115 // * we will retieve properties by hwid.
116 struct ConfigFileBlock {
117 ConfigFileBlock();
118 ~ConfigFileBlock();
120 PropertyMap properties;
121 HwidsSet hwids;
124 // At the moment we have only two entries in the config file, so we can live
125 // with linear search. Should consider changing data structure if number of
126 // entries gets bigger.
127 // Also, there is only one entry for each hwid, if that changes we should
128 // return vector of strings.
129 typedef std::list<ConfigFileBlock> BlockList;
130 BlockList config_struct_;
133 class StateMachine {
134 public:
135 enum State {
136 INITIAL,
137 DOWNLOADING,
138 BURNING,
141 State state() { return state_; }
143 class Observer {
144 public:
145 virtual void OnBurnStateChanged(State new_state) = 0;
146 virtual void OnError(int error_message_id) = 0;
149 StateMachine();
150 ~StateMachine();
152 bool download_started() const { return download_started_; }
153 void OnDownloadStarted() {
154 download_started_ = true;
155 state_ = DOWNLOADING;
156 OnStateChanged();
159 bool download_finished() const { return download_finished_; }
160 void OnDownloadFinished() { download_finished_ = true; }
162 void OnBurnStarted() {
163 state_ = BURNING;
164 OnStateChanged();
167 bool new_burn_posible() const { return state_ == INITIAL; }
169 void OnSuccess();
170 void OnError(int error_message_id);
172 void OnStateChanged() {
173 FOR_EACH_OBSERVER(Observer, observers_, OnBurnStateChanged(state_));
176 void AddObserver(Observer* observer) {
177 observers_.AddObserver(observer);
180 void RemoveObserver(Observer* observer) {
181 observers_.RemoveObserver(observer);
184 private:
185 bool download_started_;
186 bool download_finished_;
188 State state_;
190 ObserverList<Observer> observers_;
192 DISALLOW_COPY_AND_ASSIGN(StateMachine);
195 // This is a system-wide singleton class to manage burning the recovery media.
196 // Here is how the burning image procedure works:
197 // 0) Choose the device the image to be burned (manually via web-ui).
198 // 1) Create ImageDir, which is a working directory for the procedure.
199 // 2) Download the config file.
200 // 2-1) Fetch the config file from the server.
201 // 2-2) Parse the config file content, and extract url and name of the image
202 // file.
203 // 3) Fetch the image file.
204 // 4) Burn the image to the device.
205 // 4-1) Unzip the fetched image file.
206 // 4-2) Unmount the device from file system.
207 // 4-3) Copy the unzipped file to the device directly.
208 // Currently, this only provides some methods to start/cancel background tasks,
209 // and some accessors to obtain the current status. Other functions are
210 // in BurnController.
211 // TODO(hidehiko): Simplify the relationship among this class,
212 // BurnController and helper classes defined above.
213 class BurnManager : public net::URLFetcherDelegate,
214 public NetworkStateHandlerObserver {
215 public:
216 // Interface for classes that need to observe events for the burning image
217 // tasks.
218 class Observer {
219 public:
220 // Triggered when a burnable device is added.
221 virtual void OnDeviceAdded(const disks::DiskMountManager::Disk& disk) = 0;
223 // Triggered when a burnable device is removed.
224 virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk& disk) = 0;
226 // Triggered when a network is detected.
227 virtual void OnNetworkDetected() = 0;
229 // Triggered when burning the image is successfully done.
230 virtual void OnSuccess() = 0;
232 // Triggered during the image file downloading periodically.
233 // |estimated_remaining_time| is the remaining duration to download the
234 // remaining content estimated based on the elapsed time.
235 virtual void OnProgressWithRemainingTime(
236 ProgressType progress_type,
237 int64 received_bytes,
238 int64 total_bytes,
239 const base::TimeDelta& estimated_remaining_time) = 0;
241 // Triggered when some progress is made, but estimated_remaining_time is
242 // not available.
243 // TODO(hidehiko): We should be able to merge this method with above one.
244 virtual void OnProgress(ProgressType progress_type,
245 int64 received_bytes,
246 int64 total_bytes) = 0;
249 // Creates the global BurnManager instance.
250 static void Initialize(
251 const base::FilePath& downloads_directory,
252 scoped_refptr<net::URLRequestContextGetter> context_getter);
254 // Destroys the global BurnManager instance if it exists.
255 static void Shutdown();
257 // Returns the global BurnManager instance.
258 // Initialize() should already have been called.
259 static BurnManager* GetInstance();
261 // Add an observer.
262 void AddObserver(Observer* observer);
264 // Remove an observer.
265 void RemoveObserver(Observer* observer);
267 // Returns devices on which we can burn recovery image.
268 std::vector<disks::DiskMountManager::Disk> GetBurnableDevices();
270 // Cancels a currently running task of burning recovery image.
271 // Note: currently we only support Cancel method, which may look asymmetry
272 // because there is no method to start the task. It is just because that
273 // we are on the way of refactoring.
274 // TODO(hidehiko): Introduce Start method, which actually starts a whole
275 // image burning task, including config/image file fetching and unzipping.
276 void Cancel();
278 // Error is usually detected by all existing Burn handlers, but only first
279 // one that calls this method should actually process it.
280 // The |message_id| is the id for human readable error message, although
281 // here is not the place to handle UI.
282 // TODO(hidehiko): Replace it with semantical enum value.
283 // Note: currently, due to some implementation reasons, the errors can be
284 // observed in outside classes, and this method is public to be accessed from
285 // them.
286 // TODO(hidehiko): Refactor the structure.
287 void OnError(int message_id);
289 // Creates URL image should be fetched from.
290 // Must be called from UI thread.
291 void FetchConfigFile();
293 // Fetch a zipped recovery image.
294 void FetchImage();
296 // Burns the image of |zip_image_file_path_| and |image_file_name|
297 // to |target_device_path_| and |target_file_path_|.
298 // TODO(hidehiko): The name "Burn" sounds confusing because there are two
299 // meaning here.
300 // 1) In wider sense, Burn means a whole process, including config/image
301 // file fetching, or file unzipping.
302 // 2) In narrower sense, Burn means just write the image onto a device.
303 // To avoid such a confusion, rename the method.
304 void DoBurn();
306 // Cancels the image burning.
307 // TODO(hidehiko): Rename this method along with the renaming of DoBurn.
308 void CancelBurnImage();
310 // Cancel fetching image.
311 void CancelImageFetch();
313 // URLFetcherDelegate overrides:
314 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
315 virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source,
316 int64 current,
317 int64 total) OVERRIDE;
319 // NetworkStateHandlerObserver override.
320 virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
322 // Creates directory image will be downloaded to.
323 // Must be called from FILE thread.
324 void CreateImageDir();
326 // Returns the directory to which the recovery image should be downloaded.
327 // If the directory hasn't been previously created, an empty path is returned
328 // (in which case |CreateImageDir()| should be called).
329 base::FilePath GetImageDir();
331 const base::FilePath& target_device_path() { return target_device_path_; }
332 void set_target_device_path(const base::FilePath& path) {
333 target_device_path_ = path;
336 const base::FilePath& target_file_path() { return target_file_path_; }
337 void set_target_file_path(const base::FilePath& path) {
338 target_file_path_ = path;
341 void ResetTargetPaths() {
342 target_device_path_.clear();
343 target_file_path_.clear();
346 StateMachine* state_machine() const { return state_machine_.get(); }
348 private:
349 BurnManager(const base::FilePath& downloads_directory,
350 scoped_refptr<net::URLRequestContextGetter> context_getter);
351 virtual ~BurnManager();
353 void UpdateBurnStatus(BurnEvent evt, const ImageBurnStatus& status);
355 void OnImageDirCreated(bool success);
356 void ConfigFileFetched(bool fetched, const std::string& content);
358 void OnImageUnzipped(scoped_refptr<base::RefCountedString> source_image_file);
359 void OnDevicesUnmounted(bool success);
360 void OnBurnImageFail();
361 void OnBurnFinished(const std::string& target_path,
362 bool success,
363 const std::string& error);
364 void OnBurnProgressUpdate(const std::string& target_path,
365 int64 num_bytes_burnt,
366 int64 total_size);
368 void NotifyDeviceAdded(const disks::DiskMountManager::Disk& disk);
369 void NotifyDeviceRemoved(const disks::DiskMountManager::Disk& disk);
371 BurnDeviceHandler device_handler_;
373 bool image_dir_created_;
374 bool unzipping_;
375 bool cancelled_;
376 bool burning_;
377 bool block_burn_signals_;
379 base::FilePath image_dir_;
380 base::FilePath zip_image_file_path_;
381 base::FilePath source_image_path_;
382 base::FilePath target_device_path_;
383 base::FilePath target_file_path_;
385 GURL config_file_url_;
386 bool config_file_fetched_;
387 std::string image_file_name_;
388 GURL image_download_url_;
390 scoped_ptr<StateMachine> state_machine_;
392 scoped_ptr<net::URLFetcher> config_fetcher_;
393 scoped_ptr<net::URLFetcher> image_fetcher_;
395 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
397 base::TimeTicks tick_image_download_start_;
398 int64 bytes_image_download_progress_last_reported_;
400 ObserverList<Observer> observers_;
402 // Note: This should remain the last member so it'll be destroyed and
403 // invalidate its weak pointers before any other members are destroyed.
404 base::WeakPtrFactory<BurnManager> weak_ptr_factory_;
406 DISALLOW_COPY_AND_ASSIGN(BurnManager);
409 } // namespace imageburner
411 } // namespace chromeos
413 #endif // CHROME_BROWSER_CHROMEOS_IMAGEBURNER_BURN_MANAGER_H_