OLD | NEW |
| (Empty) |
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::Write(const base::Closure& continuation) { | |
22 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
23 if (IsCancelled()) { | |
24 return; | |
25 } | |
26 | |
27 SetStage(image_writer_api::STAGE_WRITE); | |
28 | |
29 // TODO (haven): Unmount partitions before writing. http://crbug.com/284834 | |
30 | |
31 base::PlatformFileError result; | |
32 image_file_ = base::CreatePlatformFile( | |
33 image_path_, | |
34 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | |
35 NULL, | |
36 &result); | |
37 if (result != base::PLATFORM_FILE_OK) { | |
38 Error(error::kImageOpenError); | |
39 return; | |
40 } | |
41 | |
42 device_file_ = base::CreatePlatformFile( | |
43 device_path_, | |
44 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, | |
45 NULL, | |
46 &result); | |
47 if (result != base::PLATFORM_FILE_OK) { | |
48 Error(error::kDeviceOpenError); | |
49 base::ClosePlatformFile(image_file_); | |
50 return; | |
51 } | |
52 | |
53 int64 total_size; | |
54 base::GetFileSize(image_path_, &total_size); | |
55 | |
56 BrowserThread::PostTask( | |
57 BrowserThread::FILE, | |
58 FROM_HERE, | |
59 base::Bind(&Operation::WriteChunk, this, 0, total_size, continuation)); | |
60 } | |
61 | |
62 void Operation::WriteChunk(const int64& bytes_written, | |
63 const int64& total_size, | |
64 const base::Closure& continuation) { | |
65 if (!IsCancelled()) { | |
66 scoped_ptr<char[]> buffer(new char[kBurningBlockSize]); | |
67 int64 len = base::ReadPlatformFile( | |
68 image_file_, bytes_written, buffer.get(), kBurningBlockSize); | |
69 | |
70 if (len > 0) { | |
71 if (base::WritePlatformFile( | |
72 device_file_, bytes_written, buffer.get(), len) == len) { | |
73 int percent_curr = | |
74 kProgressComplete * (bytes_written + len) / total_size; | |
75 | |
76 SetProgress(percent_curr); | |
77 | |
78 BrowserThread::PostTask(BrowserThread::FILE, | |
79 FROM_HERE, | |
80 base::Bind(&Operation::WriteChunk, | |
81 this, | |
82 bytes_written + len, | |
83 total_size, | |
84 continuation)); | |
85 return; | |
86 } else { | |
87 Error(error::kDeviceWriteError); | |
88 } | |
89 } else if (len == 0) { | |
90 WriteComplete(continuation); | |
91 } else { // len < 0 | |
92 Error(error::kImageReadError); | |
93 } | |
94 } | |
95 | |
96 base::ClosePlatformFile(image_file_); | |
97 base::ClosePlatformFile(device_file_); | |
98 } | |
99 | |
100 void Operation::WriteComplete(const base::Closure& continuation) { | |
101 SetProgress(kProgressComplete); | |
102 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); | |
103 } | |
104 | |
105 void Operation::VerifyWrite(const base::Closure& continuation) { | |
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
107 if (IsCancelled()) { | |
108 return; | |
109 } | |
110 | |
111 SetStage(image_writer_api::STAGE_VERIFYWRITE); | |
112 | |
113 base::PlatformFileError result; | |
114 | |
115 image_file_ = base::CreatePlatformFile( | |
116 image_path_, | |
117 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | |
118 NULL, | |
119 &result); | |
120 if (result != base::PLATFORM_FILE_OK) { | |
121 Error(error::kImageOpenError); | |
122 return; | |
123 } | |
124 | |
125 device_file_ = base::CreatePlatformFile( | |
126 device_path_, | |
127 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | |
128 NULL, | |
129 &result); | |
130 if (result != base::PLATFORM_FILE_OK) { | |
131 Error(error::kDeviceOpenError); | |
132 base::ClosePlatformFile(image_file_); | |
133 return; | |
134 } | |
135 | |
136 int64 total_size; | |
137 base::GetFileSize(image_path_, &total_size); | |
138 | |
139 BrowserThread::PostTask( | |
140 BrowserThread::FILE, | |
141 FROM_HERE, | |
142 base::Bind( | |
143 &Operation::VerifyWriteChunk, this, 0, total_size, continuation)); | |
144 } | |
145 | |
146 void Operation::VerifyWriteChunk(const int64& bytes_processed, | |
147 const int64& total_size, | |
148 const base::Closure& continuation) { | |
149 if (!IsCancelled()) { | |
150 scoped_ptr<char[]> source_buffer(new char[kBurningBlockSize]); | |
151 scoped_ptr<char[]> target_buffer(new char[kBurningBlockSize]); | |
152 | |
153 int64 image_bytes_read = base::ReadPlatformFile( | |
154 image_file_, bytes_processed, source_buffer.get(), kBurningBlockSize); | |
155 | |
156 if (image_bytes_read > 0) { | |
157 int64 device_bytes_read = base::ReadPlatformFile( | |
158 device_file_, bytes_processed, target_buffer.get(), image_bytes_read); | |
159 if (image_bytes_read == device_bytes_read && | |
160 memcmp(source_buffer.get(), target_buffer.get(), image_bytes_read) == | |
161 0) { | |
162 int percent_curr = kProgressComplete * | |
163 (bytes_processed + image_bytes_read) / total_size; | |
164 | |
165 SetProgress(percent_curr); | |
166 | |
167 BrowserThread::PostTask(BrowserThread::FILE, | |
168 FROM_HERE, | |
169 base::Bind(&Operation::VerifyWriteChunk, | |
170 this, | |
171 bytes_processed + image_bytes_read, | |
172 total_size, | |
173 continuation)); | |
174 return; | |
175 } else { | |
176 Error(error::kVerificationFailed); | |
177 } | |
178 } else if (image_bytes_read == 0) { | |
179 VerifyWriteComplete(continuation); | |
180 } else { // len < 0 | |
181 Error(error::kImageReadError); | |
182 } | |
183 } | |
184 | |
185 base::ClosePlatformFile(image_file_); | |
186 base::ClosePlatformFile(device_file_); | |
187 } | |
188 | |
189 void Operation::VerifyWriteComplete(const base::Closure& continuation) { | |
190 SetProgress(kProgressComplete); | |
191 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); | |
192 } | |
193 | |
194 } // namespace image_writer | |
195 } // namespace extensions | |
OLD | NEW |