- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / image_writer_private / operation_linux.cc
1 // Copyright 2013 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 "base/file_util.h"
6 #include "base/files/file_enumerator.h"
7 #include "base/threading/worker_pool.h"
8 #include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
9 #include "chrome/browser/extensions/api/image_writer_private/operation.h"
10 #include "chrome/browser/extensions/api/image_writer_private/operation_manager.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "third_party/zlib/google/zip.h"
13
14 namespace extensions {
15 namespace image_writer {
16
17 using content::BrowserThread;
18
19 const int kBurningBlockSize = 8 * 1024;  // 8 KiB
20
21 void Operation::WriteStart() {
22   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
23   if (IsCancelled()) {
24     return;
25   }
26
27   if (image_path_.empty()) {
28     Error(error::kImageNotFound);
29     return;
30   }
31
32   DVLOG(1) << "Starting write of " << image_path_.value()
33            << " to " << storage_unit_id_;
34
35   SetStage(image_writer_api::STAGE_WRITE);
36
37   // TODO (haven): Unmount partitions before writing. http://crbug.com/284834
38
39   scoped_ptr<image_writer_utils::ImageReader> reader(
40       new image_writer_utils::ImageReader());
41   scoped_ptr<image_writer_utils::ImageWriter> writer(
42       new image_writer_utils::ImageWriter());
43   base::FilePath storage_path(storage_unit_id_);
44
45   if (reader->Open(image_path_)) {
46     if (!writer->Open(storage_path)) {
47       reader->Close();
48       Error(error::kOpenDevice);
49       return;
50     }
51   } else {
52     Error(error::kOpenImage);
53     return;
54   }
55
56   BrowserThread::PostTask(
57     BrowserThread::FILE,
58     FROM_HERE,
59     base::Bind(&Operation::WriteChunk,
60                this,
61                base::Passed(&reader),
62                base::Passed(&writer),
63                0));
64 }
65
66 void Operation::WriteChunk(
67     scoped_ptr<image_writer_utils::ImageReader> reader,
68     scoped_ptr<image_writer_utils::ImageWriter> writer,
69     int64 bytes_written) {
70   if (IsCancelled()) {
71     WriteCleanUp(reader.Pass(), writer.Pass());
72     return;
73   }
74
75   char buffer[kBurningBlockSize];
76   int64 image_size = reader->GetSize();
77   int len = reader->Read(buffer, kBurningBlockSize);
78
79   if (len > 0) {
80     if (writer->Write(buffer, len) == len) {
81       int percent_prev = kProgressComplete * bytes_written / image_size;
82       int percent_curr = kProgressComplete * (bytes_written + len) / image_size;
83
84       if (percent_curr > percent_prev) {
85         SetProgress(percent_curr);
86       }
87
88       BrowserThread::PostTask(
89         BrowserThread::FILE,
90         FROM_HERE,
91         base::Bind(&Operation::WriteChunk,
92                    this,
93                    base::Passed(&reader),
94                    base::Passed(&writer),
95                    bytes_written + len));
96     } else {
97       WriteCleanUp(reader.Pass(), writer.Pass());
98       Error(error::kWriteImage);
99     }
100   } else if (len == 0) {
101     if (bytes_written == image_size) {
102       if (WriteCleanUp(reader.Pass(), writer.Pass())) {
103         BrowserThread::PostTask(
104           BrowserThread::FILE,
105           FROM_HERE,
106           base::Bind(&Operation::WriteComplete,
107                      this));
108       }
109     } else {
110       WriteCleanUp(reader.Pass(), writer.Pass());
111       Error(error::kPrematureEndOfFile);
112     }
113   } else { // len < 0
114     WriteCleanUp(reader.Pass(), writer.Pass());
115     Error(error::kReadImage);
116   }
117 }
118
119 bool Operation::WriteCleanUp(
120     scoped_ptr<image_writer_utils::ImageReader> reader,
121     scoped_ptr<image_writer_utils::ImageWriter> writer) {
122
123   bool success = true;
124   if (!reader->Close()) {
125     Error(error::kCloseImage);
126     success = false;
127   }
128
129   if (!writer->Close()) {
130     Error(error::kCloseDevice);
131     success = false;
132   }
133   return success;
134 }
135
136 void Operation::WriteComplete() {
137
138   DVLOG(2) << "Completed write of " << image_path_.value();
139   SetProgress(kProgressComplete);
140
141   BrowserThread::PostTask(
142     BrowserThread::FILE,
143     FROM_HERE,
144     base::Bind(&Operation::VerifyWriteStart,
145                this));
146 }
147
148 void Operation::VerifyWriteStart() {
149   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
150   if (IsCancelled()) {
151     return;
152   }
153
154   DVLOG(1) << "Starting verification stage.";
155
156   SetStage(image_writer_api::STAGE_VERIFYWRITE);
157
158   scoped_ptr<base::FilePath> image_path(new base::FilePath(image_path_));
159
160   GetMD5SumOfFile(
161       image_path.Pass(),
162       -1,
163       0, // progress_offset
164       50, // progress_scale
165       base::Bind(&Operation::VerifyWriteStage2,
166                  this));
167 }
168
169 void Operation::VerifyWriteStage2(
170     scoped_ptr<std::string> image_hash) {
171   DVLOG(1) << "Building MD5 sum of device: " << storage_unit_id_;
172
173   int64 image_size;
174   scoped_ptr<base::FilePath> device_path(new base::FilePath(storage_unit_id_));
175
176   if (!file_util::GetFileSize(image_path_, &image_size)){
177     Error(error::kImageSize);
178     return;
179   }
180
181   GetMD5SumOfFile(
182       device_path.Pass(),
183       image_size,
184       50, // progress_offset
185       50, // progress_scale
186       base::Bind(&Operation::VerifyWriteCompare,
187                  this,
188                  base::Passed(&image_hash)));
189 }
190
191 void Operation::VerifyWriteCompare(
192     scoped_ptr<std::string> image_hash,
193     scoped_ptr<std::string> device_hash) {
194   DVLOG(1) << "Comparing hashes: " << *image_hash << " vs " << *device_hash;
195
196   if (*image_hash != *device_hash) {
197     Error(error::kWriteHash);
198     return;
199   }
200
201   DVLOG(2) << "Completed write verification of " << image_path_.value();
202
203   SetProgress(kProgressComplete);
204
205   Finish();
206 }
207
208 }  // namespace image_writer
209 }  // namespace extensions