OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "third_party/zlib/google/zip_reader.h" | 5 #include "third_party/zlib/google/zip_reader.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop/message_loop.h" |
9 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
10 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
11 #include "net/base/file_stream.h" | 12 #include "net/base/file_stream.h" |
12 #include "third_party/zlib/google/zip_internal.h" | 13 #include "third_party/zlib/google/zip_internal.h" |
13 | 14 |
14 #if defined(USE_SYSTEM_MINIZIP) | 15 #if defined(USE_SYSTEM_MINIZIP) |
15 #include <minizip/unzip.h> | 16 #include <minizip/unzip.h> |
16 #else | 17 #else |
17 #include "third_party/zlib/contrib/minizip/unzip.h" | 18 #include "third_party/zlib/contrib/minizip/unzip.h" |
18 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 exploded_time.second = raw_file_info.tmu_date.tm_sec; | 62 exploded_time.second = raw_file_info.tmu_date.tm_sec; |
62 exploded_time.millisecond = 0; | 63 exploded_time.millisecond = 0; |
63 if (exploded_time.HasValidValues()) { | 64 if (exploded_time.HasValidValues()) { |
64 last_modified_ = base::Time::FromLocalExploded(exploded_time); | 65 last_modified_ = base::Time::FromLocalExploded(exploded_time); |
65 } else { | 66 } else { |
66 // Use Unix time epoch if the time stamp data is invalid. | 67 // Use Unix time epoch if the time stamp data is invalid. |
67 last_modified_ = base::Time::UnixEpoch(); | 68 last_modified_ = base::Time::UnixEpoch(); |
68 } | 69 } |
69 } | 70 } |
70 | 71 |
71 ZipReader::ZipReader() { | 72 ZipReader::ZipReader() |
| 73 : weak_ptr_factory_(this) { |
72 Reset(); | 74 Reset(); |
73 } | 75 } |
74 | 76 |
75 ZipReader::~ZipReader() { | 77 ZipReader::~ZipReader() { |
76 Close(); | 78 Close(); |
77 } | 79 } |
78 | 80 |
79 bool ZipReader::Open(const base::FilePath& zip_file_path) { | 81 bool ZipReader::Open(const base::FilePath& zip_file_path) { |
80 DCHECK(!zip_file_); | 82 DCHECK(!zip_file_); |
81 | 83 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 unzCloseCurrentFile(zip_file_); | 236 unzCloseCurrentFile(zip_file_); |
235 | 237 |
236 if (current_entry_info()->last_modified() != base::Time::UnixEpoch()) | 238 if (current_entry_info()->last_modified() != base::Time::UnixEpoch()) |
237 base::TouchFile(output_file_path, | 239 base::TouchFile(output_file_path, |
238 base::Time::Now(), | 240 base::Time::Now(), |
239 current_entry_info()->last_modified()); | 241 current_entry_info()->last_modified()); |
240 | 242 |
241 return success; | 243 return success; |
242 } | 244 } |
243 | 245 |
| 246 void ZipReader::ExtractCurrentEntryToFilePathAsync( |
| 247 const base::FilePath& output_file_path, |
| 248 const SuccessCallback& success_callback, |
| 249 const FailureCallback& failure_callback, |
| 250 const ProgressCallback& progress_callback) { |
| 251 DCHECK(zip_file_); |
| 252 DCHECK(current_entry_info_.get()); |
| 253 |
| 254 // If this is a directory, just create it and return. |
| 255 if (current_entry_info()->is_directory()) { |
| 256 if (base::CreateDirectory(output_file_path)) { |
| 257 base::MessageLoopProxy::current()->PostTask(FROM_HERE, success_callback); |
| 258 } else { |
| 259 DVLOG(1) << "Unzip failed: unable to create directory."; |
| 260 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
| 261 } |
| 262 return; |
| 263 } |
| 264 |
| 265 if (unzOpenCurrentFile(zip_file_) != UNZ_OK) { |
| 266 DVLOG(1) << "Unzip failed: unable to open current zip entry."; |
| 267 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
| 268 return; |
| 269 } |
| 270 |
| 271 base::FilePath output_dir_path = output_file_path.DirName(); |
| 272 if (!base::CreateDirectory(output_dir_path)) { |
| 273 DVLOG(1) << "Unzip failed: unable to create containing directory."; |
| 274 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
| 275 return; |
| 276 } |
| 277 |
| 278 const int flags = (base::PLATFORM_FILE_CREATE_ALWAYS | |
| 279 base::PLATFORM_FILE_WRITE); |
| 280 bool created = false; |
| 281 base::PlatformFileError platform_file_error; |
| 282 base::PlatformFile output_file = CreatePlatformFile(output_file_path, |
| 283 flags, |
| 284 &created, |
| 285 &platform_file_error); |
| 286 |
| 287 if (platform_file_error != base::PLATFORM_FILE_OK) { |
| 288 DVLOG(1) << "Unzip failed: unable to create platform file at " |
| 289 << output_file_path.value(); |
| 290 base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
| 291 return; |
| 292 } |
| 293 |
| 294 base::MessageLoop::current()->PostTask( |
| 295 FROM_HERE, |
| 296 base::Bind(&ZipReader::ExtractChunk, |
| 297 weak_ptr_factory_.GetWeakPtr(), |
| 298 output_file, |
| 299 success_callback, |
| 300 failure_callback, |
| 301 progress_callback, |
| 302 0 /* initial offset */)); |
| 303 } |
| 304 |
244 bool ZipReader::ExtractCurrentEntryIntoDirectory( | 305 bool ZipReader::ExtractCurrentEntryIntoDirectory( |
245 const base::FilePath& output_directory_path) { | 306 const base::FilePath& output_directory_path) { |
246 DCHECK(current_entry_info_.get()); | 307 DCHECK(current_entry_info_.get()); |
247 | 308 |
248 base::FilePath output_file_path = output_directory_path.Append( | 309 base::FilePath output_file_path = output_directory_path.Append( |
249 current_entry_info()->file_path()); | 310 current_entry_info()->file_path()); |
250 return ExtractCurrentEntryToFilePath(output_file_path); | 311 return ExtractCurrentEntryToFilePath(output_file_path); |
251 } | 312 } |
252 | 313 |
253 #if defined(OS_POSIX) | 314 #if defined(OS_POSIX) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 return true; | 367 return true; |
307 } | 368 } |
308 | 369 |
309 void ZipReader::Reset() { | 370 void ZipReader::Reset() { |
310 zip_file_ = NULL; | 371 zip_file_ = NULL; |
311 num_entries_ = 0; | 372 num_entries_ = 0; |
312 reached_end_ = false; | 373 reached_end_ = false; |
313 current_entry_info_.reset(); | 374 current_entry_info_.reset(); |
314 } | 375 } |
315 | 376 |
| 377 void ZipReader::ExtractChunk(base::PlatformFile output_file, |
| 378 const SuccessCallback& success_callback, |
| 379 const FailureCallback& failure_callback, |
| 380 const ProgressCallback& progress_callback, |
| 381 const int64 offset) { |
| 382 char buffer[internal::kZipBufSize]; |
| 383 |
| 384 const int num_bytes_read = unzReadCurrentFile(zip_file_, |
| 385 buffer, |
| 386 internal::kZipBufSize); |
| 387 |
| 388 if (num_bytes_read == 0) { |
| 389 unzCloseCurrentFile(zip_file_); |
| 390 base::ClosePlatformFile(output_file); |
| 391 success_callback.Run(); |
| 392 } else if (num_bytes_read < 0) { |
| 393 DVLOG(1) << "Unzip failed: error while reading zipfile " |
| 394 << "(" << num_bytes_read << ")"; |
| 395 base::ClosePlatformFile(output_file); |
| 396 failure_callback.Run(); |
| 397 } else { |
| 398 if (num_bytes_read != base::WritePlatformFile(output_file, |
| 399 offset, |
| 400 buffer, |
| 401 num_bytes_read)) { |
| 402 DVLOG(1) << "Unzip failed: unable to write all bytes to target."; |
| 403 base::ClosePlatformFile(output_file); |
| 404 failure_callback.Run(); |
| 405 return; |
| 406 } |
| 407 |
| 408 int64 current_progress = offset + num_bytes_read; |
| 409 |
| 410 progress_callback.Run(current_progress); |
| 411 |
| 412 base::MessageLoop::current()->PostTask( |
| 413 FROM_HERE, |
| 414 base::Bind(&ZipReader::ExtractChunk, |
| 415 weak_ptr_factory_.GetWeakPtr(), |
| 416 output_file, |
| 417 success_callback, |
| 418 failure_callback, |
| 419 progress_callback, |
| 420 current_progress)); |
| 421 |
| 422 } |
| 423 } |
| 424 |
| 425 |
316 } // namespace zip | 426 } // namespace zip |
OLD | NEW |