Index: third_party/zlib/google/zip_reader.cc |
diff --git a/third_party/zlib/google/zip_reader.cc b/third_party/zlib/google/zip_reader.cc |
index 8787254d28f0c87bfe0c5041580a3e288dca2d73..7b7870ee981daf4287255dc50475890f094901e7 100644 |
--- a/third_party/zlib/google/zip_reader.cc |
+++ b/third_party/zlib/google/zip_reader.cc |
@@ -6,6 +6,7 @@ |
#include "base/file_util.h" |
#include "base/logging.h" |
+#include "base/message_loop/message_loop.h" |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "net/base/file_stream.h" |
@@ -68,7 +69,8 @@ ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip, |
} |
} |
-ZipReader::ZipReader() { |
+ZipReader::ZipReader() |
+ : weak_ptr_factory_(this) { |
Reset(); |
} |
@@ -241,6 +243,65 @@ bool ZipReader::ExtractCurrentEntryToFilePath( |
return success; |
} |
+void ZipReader::ExtractCurrentEntryToFilePathAsync( |
+ const base::FilePath& output_file_path, |
+ const SuccessCallback& success_callback, |
+ const FailureCallback& failure_callback, |
+ const ProgressCallback& progress_callback) { |
+ DCHECK(zip_file_); |
+ DCHECK(current_entry_info_.get()); |
+ |
+ // If this is a directory, just create it and return. |
+ if (current_entry_info()->is_directory()) { |
+ if (base::CreateDirectory(output_file_path)) { |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, success_callback); |
+ } else { |
+ DVLOG(1) << "Unzip failed: unable to create directory."; |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
+ } |
+ return; |
+ } |
+ |
+ if (unzOpenCurrentFile(zip_file_) != UNZ_OK) { |
+ DVLOG(1) << "Unzip failed: unable to open current zip entry."; |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
+ return; |
+ } |
+ |
+ base::FilePath output_dir_path = output_file_path.DirName(); |
+ if (!base::CreateDirectory(output_dir_path)) { |
+ DVLOG(1) << "Unzip failed: unable to create containing directory."; |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
+ return; |
+ } |
+ |
+ const int flags = (base::PLATFORM_FILE_CREATE_ALWAYS | |
+ base::PLATFORM_FILE_WRITE); |
+ bool created = false; |
+ base::PlatformFileError platform_file_error; |
+ base::PlatformFile output_file = CreatePlatformFile(output_file_path, |
+ flags, |
+ &created, |
+ &platform_file_error); |
+ |
+ if (platform_file_error != base::PLATFORM_FILE_OK) { |
+ DVLOG(1) << "Unzip failed: unable to create platform file at " |
+ << output_file_path.value(); |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, failure_callback); |
+ return; |
+ } |
+ |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ZipReader::ExtractChunk, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ output_file, |
+ success_callback, |
+ failure_callback, |
+ progress_callback, |
+ 0 /* initial offset */)); |
+} |
+ |
bool ZipReader::ExtractCurrentEntryIntoDirectory( |
const base::FilePath& output_directory_path) { |
DCHECK(current_entry_info_.get()); |
@@ -313,4 +374,53 @@ void ZipReader::Reset() { |
current_entry_info_.reset(); |
} |
+void ZipReader::ExtractChunk(base::PlatformFile output_file, |
+ const SuccessCallback& success_callback, |
+ const FailureCallback& failure_callback, |
+ const ProgressCallback& progress_callback, |
+ const int64 offset) { |
+ char buffer[internal::kZipBufSize]; |
+ |
+ const int num_bytes_read = unzReadCurrentFile(zip_file_, |
+ buffer, |
+ internal::kZipBufSize); |
+ |
+ if (num_bytes_read == 0) { |
+ unzCloseCurrentFile(zip_file_); |
+ base::ClosePlatformFile(output_file); |
+ success_callback.Run(); |
+ } else if (num_bytes_read < 0) { |
+ DVLOG(1) << "Unzip failed: error while reading zipfile " |
+ << "(" << num_bytes_read << ")"; |
+ base::ClosePlatformFile(output_file); |
+ failure_callback.Run(); |
+ } else { |
+ if (num_bytes_read != base::WritePlatformFile(output_file, |
+ offset, |
+ buffer, |
+ num_bytes_read)) { |
+ DVLOG(1) << "Unzip failed: unable to write all bytes to target."; |
+ base::ClosePlatformFile(output_file); |
+ failure_callback.Run(); |
+ return; |
+ } |
+ |
+ int64 current_progress = offset + num_bytes_read; |
+ |
+ progress_callback.Run(current_progress); |
+ |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ZipReader::ExtractChunk, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ output_file, |
+ success_callback, |
+ failure_callback, |
+ progress_callback, |
+ current_progress)); |
+ |
+ } |
+} |
+ |
+ |
} // namespace zip |