Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: ui/file_manager/zip_archiver/cpp/volume_reader_javascript_stream.cc

Issue 2807063002: Replace Libarchive with MiniZip. (Closed)
Patch Set: Fix a few nits. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium OS Authors. All rights reserved. 1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "volume_reader_javascript_stream.h" 5 #include "volume_reader_javascript_stream.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "archive.h" 10 #include "third_party/zlib/contrib/minizip/unzip.h"
11
11 #include "ppapi/cpp/logging.h" 12 #include "ppapi/cpp/logging.h"
12 13
13 VolumeReaderJavaScriptStream::VolumeReaderJavaScriptStream( 14 VolumeReaderJavaScriptStream::VolumeReaderJavaScriptStream(
14 int64_t archive_size, 15 int64_t archive_size,
15 JavaScriptRequestorInterface* requestor) 16 JavaScriptRequestorInterface* requestor)
16 : archive_size_(archive_size), 17 : archive_size_(archive_size),
17 requestor_(requestor), 18 requestor_(requestor),
18 available_data_(false), 19 available_data_(false),
19 read_error_(false), 20 read_error_(false),
20 passphrase_error_(false), 21 passphrase_error_(false),
21 offset_(0), 22 offset_(0),
22 last_read_chunk_offset_(-1) /* For first call -1 will force a chunk 23 last_read_chunk_offset_(-1) /* For first call -1 will force a chunk
23 request from JavaScript as offset 24 request from JavaScript as offset
24 parameter is 0. */, 25 parameter is 0. */,
25 read_ahead_array_buffer_ptr_(&first_array_buffer_) { 26 read_ahead_array_buffer_ptr_(&first_array_buffer_) {
26 pthread_mutex_init(&shared_state_lock_, NULL); 27 pthread_mutex_init(&shared_state_lock_, nullptr);
27 pthread_cond_init(&available_data_cond_, NULL); 28 pthread_cond_init(&available_data_cond_, nullptr);
28 pthread_cond_init(&available_passphrase_cond_, NULL); 29 pthread_cond_init(&available_passphrase_cond_, nullptr);
29 30
30 // Dummy Map the second buffer as first buffer is used for read ahead by 31 // Dummy Map the second buffer as first buffer is used for read ahead by
31 // read_ahead_array_buffer_ptr_. This operation is required in order for Unmap 32 // read_ahead_array_buffer_ptr_. This operation is required in order for Unmap
32 // to correctly work in the destructor and VolumeReaderJavaScriptStream::Read. 33 // to correctly work in the destructor and VolumeReaderJavaScriptStream::Read.
33 second_array_buffer_.Map(); 34 second_array_buffer_.Map();
34 } 35 }
35 36
36 VolumeReaderJavaScriptStream::~VolumeReaderJavaScriptStream() { 37 VolumeReaderJavaScriptStream::~VolumeReaderJavaScriptStream() {
37 pthread_mutex_destroy(&shared_state_lock_); 38 pthread_mutex_destroy(&shared_state_lock_);
38 pthread_cond_destroy(&available_data_cond_); 39 pthread_cond_destroy(&available_data_cond_);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 114
114 pthread_mutex_lock(&shared_state_lock_); 115 pthread_mutex_lock(&shared_state_lock_);
115 116
116 // No more data, so signal end of reading. 117 // No more data, so signal end of reading.
117 if (offset_ >= archive_size_) { 118 if (offset_ >= archive_size_) {
118 pthread_mutex_unlock(&shared_state_lock_); 119 pthread_mutex_unlock(&shared_state_lock_);
119 return 0; 120 return 0;
120 } 121 }
121 122
122 // Call in case of first read or read after Seek and Skip. 123 // Call in case of first read or read after Seek and Skip.
123 if (last_read_chunk_offset_ != offset_) 124 if (last_read_chunk_offset_ != offset_ || !available_data_)
124 RequestChunk(bytes_to_read); 125 RequestChunk(bytes_to_read);
125 126
126 if (!available_data_) { 127 if (!available_data_) {
127 // Wait for data from JavaScript. 128 // Wait for data from JavaScript.
128 while (!available_data_) { // Check again available data as first call 129 while (!available_data_) { // Check again available data as first call
129 // was done outside guarded zone. 130 // was done outside guarded zone.
130 if (read_error_) { 131 if (read_error_) {
131 pthread_mutex_unlock(&shared_state_lock_); 132 pthread_mutex_unlock(&shared_state_lock_);
132 return ARCHIVE_FATAL; 133 return -1;
133 } 134 }
134 pthread_cond_wait(&available_data_cond_, &shared_state_lock_); 135 pthread_cond_wait(&available_data_cond_, &shared_state_lock_);
135 } 136 }
136 } 137 }
137 138
138 if (read_error_) { // Read ahead failed. 139 if (read_error_) { // Read ahead failed.
139 pthread_mutex_unlock(&shared_state_lock_); 140 pthread_mutex_unlock(&shared_state_lock_);
140 return ARCHIVE_FATAL; 141 return -1;
141 } 142 }
142 143
143 // Make data available for libarchive custom read. No need to lock this part. 144 // Make data available for libarchive custom read. No need to lock this part.
144 // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only 145 // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only
145 // function that can set available_data_ back to false and let 146 // function that can set available_data_ back to false and let
146 // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But 147 // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But
147 // reading ahead is done only at the end of this function after the buffers 148 // reading ahead is done only at the end of this function after the buffers
148 // are switched. 149 // are switched.
149 *destination_buffer = read_ahead_array_buffer_ptr_->Map(); 150 *destination_buffer = read_ahead_array_buffer_ptr_->Map();
150 int64_t bytes_read = 151 int64_t bytes_read =
(...skipping 29 matching lines...) Expand all
180 pthread_mutex_unlock(&shared_state_lock_); 181 pthread_mutex_unlock(&shared_state_lock_);
181 182
182 return bytes_read; 183 return bytes_read;
183 } 184 }
184 185
185 int64_t VolumeReaderJavaScriptStream::Seek(int64_t offset, int whence) { 186 int64_t VolumeReaderJavaScriptStream::Seek(int64_t offset, int whence) {
186 pthread_mutex_lock(&shared_state_lock_); 187 pthread_mutex_lock(&shared_state_lock_);
187 188
188 int64_t new_offset = offset_; 189 int64_t new_offset = offset_;
189 switch (whence) { 190 switch (whence) {
190 case SEEK_SET: 191 case ZLIB_FILEFUNC_SEEK_SET:
191 new_offset = offset; 192 new_offset = offset;
192 break; 193 break;
193 case SEEK_CUR: 194 case ZLIB_FILEFUNC_SEEK_CUR:
194 new_offset += offset; 195 new_offset += offset;
195 break; 196 break;
196 case SEEK_END: 197 case ZLIB_FILEFUNC_SEEK_END:
197 new_offset = archive_size_ + offset; 198 new_offset = archive_size_ + offset;
198 break; 199 break;
199 default: 200 default:
200 PP_NOTREACHED(); 201 PP_NOTREACHED();
201 pthread_mutex_unlock(&shared_state_lock_); 202 pthread_mutex_unlock(&shared_state_lock_);
202 return ARCHIVE_FATAL; 203 return -1;
203 } 204 }
204 205
205 if (new_offset < 0 || new_offset > archive_size_) { 206 if (new_offset < 0) {
206 pthread_mutex_unlock(&shared_state_lock_); 207 pthread_mutex_unlock(&shared_state_lock_);
207 return ARCHIVE_FATAL; 208 return -1;
208 } 209 }
209 210
210 offset_ = new_offset; 211 offset_ = new_offset;
211 pthread_mutex_unlock(&shared_state_lock_); 212 pthread_mutex_unlock(&shared_state_lock_);
212 213
213 return new_offset; 214 return new_offset;
214 } 215 }
215 216
216 int64_t VolumeReaderJavaScriptStream::Skip(int64_t bytes_to_skip) {
217 pthread_mutex_lock(&shared_state_lock_);
218 // Invalid bytes_to_skip. This "if" can be triggered for corrupted archives.
219 // We return 0 instead of ARCHIVE_FATAL in order for libarchive to use normal
220 // Read and return the correct error. In case we return ARCHIVE_FATAL here
221 // then libarchive just stops without telling us why it wasn't able to
222 // process the archive.
223 if (archive_size_ - offset_ < bytes_to_skip || bytes_to_skip < 0) {
224 pthread_mutex_unlock(&shared_state_lock_);
225 return 0;
226 }
227
228 offset_ += bytes_to_skip;
229 pthread_mutex_unlock(&shared_state_lock_);
230
231 return bytes_to_skip;
232 }
233
234 void VolumeReaderJavaScriptStream::SetRequestId(const std::string& request_id) { 217 void VolumeReaderJavaScriptStream::SetRequestId(const std::string& request_id) {
235 // No lock necessary, as request_id is used by one thread only. 218 // No lock necessary, as request_id is used by one thread only.
236 request_id_ = request_id; 219 request_id_ = request_id;
237 } 220 }
238 221
239 const char* VolumeReaderJavaScriptStream::Passphrase() { 222 const char* VolumeReaderJavaScriptStream::Passphrase() {
240 // The error is not recoverable. Once passphrase fails to be provided, it is 223 // The error is not recoverable. Once passphrase fails to be provided, it is
241 // never asked again. Note, that still users are able to retry entering the 224 // never asked again. Note, that still users are able to retry entering the
242 // password, unless they click Cancel. 225 // password, unless they click Cancel.
243 pthread_mutex_lock(&shared_state_lock_); 226 pthread_mutex_lock(&shared_state_lock_);
244 if (passphrase_error_) { 227 if (passphrase_error_) {
245 pthread_mutex_unlock(&shared_state_lock_); 228 pthread_mutex_unlock(&shared_state_lock_);
246 return NULL; 229 return nullptr;
247 } 230 }
248 pthread_mutex_unlock(&shared_state_lock_); 231 pthread_mutex_unlock(&shared_state_lock_);
249 232
250 // Request the passphrase outside of the lock. 233 // Request the passphrase outside of the lock.
251 requestor_->RequestPassphrase(request_id_); 234 requestor_->RequestPassphrase(request_id_);
252 235
253 pthread_mutex_lock(&shared_state_lock_); 236 pthread_mutex_lock(&shared_state_lock_);
254 // Wait for the passphrase from JavaScript. 237 // Wait for the passphrase from JavaScript.
255 pthread_cond_wait(&available_passphrase_cond_, &shared_state_lock_); 238 pthread_cond_wait(&available_passphrase_cond_, &shared_state_lock_);
256 const char* result = NULL; 239 const char* result = nullptr;
257 if (!passphrase_error_) 240 if (!passphrase_error_)
258 result = strdup(available_passphrase_.c_str()); 241 result = strdup(available_passphrase_.c_str());
259 pthread_mutex_unlock(&shared_state_lock_); 242 pthread_mutex_unlock(&shared_state_lock_);
260 243
261 return result; 244 return result;
262 } 245 }
263 246
264 void VolumeReaderJavaScriptStream::RequestChunk(int64_t length) { 247 void VolumeReaderJavaScriptStream::RequestChunk(int64_t length) {
265 // Read next chunk only if not at the end of archive. 248 // Read next chunk only if not at the end of archive.
266 if (archive_size_ <= offset_) 249 if (archive_size_ <= offset_)
267 return; 250 return;
268 251
269 int64_t bytes_to_read = 252 int64_t bytes_to_read =
270 std::min(length, archive_size_ - offset_ /* Positive check above. */); 253 std::min(length, archive_size_ - offset_ /* Positive check above. */);
271 available_data_ = false; 254 available_data_ = false;
272 255
273 requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read); 256 requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read);
274 } 257 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698