| Index: ui/file_manager/zip_archiver/unpacker/cpp/volume_reader_javascript_stream.cc
|
| diff --git a/ui/file_manager/zip_archiver/unpacker/cpp/volume_reader_javascript_stream.cc b/ui/file_manager/zip_archiver/unpacker/cpp/volume_reader_javascript_stream.cc
|
| deleted file mode 100644
|
| index 75a8ef6245534154ab3cb28fd3ade24fca476cb4..0000000000000000000000000000000000000000
|
| --- a/ui/file_manager/zip_archiver/unpacker/cpp/volume_reader_javascript_stream.cc
|
| +++ /dev/null
|
| @@ -1,274 +0,0 @@
|
| -// Copyright 2014 The Chromium OS Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "volume_reader_javascript_stream.h"
|
| -
|
| -#include <algorithm>
|
| -#include <limits>
|
| -
|
| -#include "archive.h"
|
| -#include "ppapi/cpp/logging.h"
|
| -
|
| -VolumeReaderJavaScriptStream::VolumeReaderJavaScriptStream(
|
| - int64_t archive_size,
|
| - JavaScriptRequestorInterface* requestor)
|
| - : archive_size_(archive_size),
|
| - requestor_(requestor),
|
| - available_data_(false),
|
| - read_error_(false),
|
| - passphrase_error_(false),
|
| - offset_(0),
|
| - last_read_chunk_offset_(-1) /* For first call -1 will force a chunk
|
| - request from JavaScript as offset
|
| - parameter is 0. */,
|
| - read_ahead_array_buffer_ptr_(&first_array_buffer_) {
|
| - pthread_mutex_init(&shared_state_lock_, NULL);
|
| - pthread_cond_init(&available_data_cond_, NULL);
|
| - pthread_cond_init(&available_passphrase_cond_, NULL);
|
| -
|
| - // Dummy Map the second buffer as first buffer is used for read ahead by
|
| - // read_ahead_array_buffer_ptr_. This operation is required in order for Unmap
|
| - // to correctly work in the destructor and VolumeReaderJavaScriptStream::Read.
|
| - second_array_buffer_.Map();
|
| -}
|
| -
|
| -VolumeReaderJavaScriptStream::~VolumeReaderJavaScriptStream() {
|
| - pthread_mutex_destroy(&shared_state_lock_);
|
| - pthread_cond_destroy(&available_data_cond_);
|
| - pthread_cond_destroy(&available_passphrase_cond_);
|
| -
|
| - // Unmap last mapped buffer. This is the other buffer to
|
| - // read_ahead_array_buffer_ptr_ as read_ahead_array_buffer_ptr_ must be
|
| - // available for SetBufferAndSignal to overwrite.
|
| - if (read_ahead_array_buffer_ptr_ != &first_array_buffer_)
|
| - first_array_buffer_.Unmap();
|
| - else
|
| - second_array_buffer_.Unmap();
|
| -};
|
| -
|
| -void VolumeReaderJavaScriptStream::SetBufferAndSignal(
|
| - const pp::VarArrayBuffer& array_buffer,
|
| - int64_t read_offset) {
|
| - PP_DCHECK(read_offset >= 0);
|
| -
|
| - // Ignore read ahead in case offset was changed using Skip or Seek and in case
|
| - // we already have available data. This can happen in case of 2+ RequestChunk
|
| - // calls done in parallel as a result of calling Read, Skip and Seek one after
|
| - // another really fast. The usage of the buffer is not guarded so in case we
|
| - // overwrite *read_ahead_array_buffer_ptr_ we will end up with memory
|
| - // corruption.
|
| - // In case read_offset and offset_ are different, then the read ahead data is
|
| - // not valid anymore, but in case they are equal and available_data_ is set to
|
| - // true then the second read ahead data is the same as the first read ahead
|
| - // data so we can just ignore it.
|
| -
|
| - // TODO(mtomasz): We don't need to discard everything. Sometimes part of the
|
| - // buffer can still be used. In such case we should use it. That can greatly
|
| - // improve traversing headers for archives with small files!
|
| -
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - if (read_offset == offset_ && !available_data_ && !read_error_) {
|
| - // Signal VolumeReaderJavaScriptStream::Read to continue execution. Copies
|
| - // buffer locally so libarchive has the buffer in memory when working with
|
| - // it. Though we acquire a lock here this call is blocking only for a few
|
| - // moments as VolumeReaderJavaScriptStream::Read will release the lock with
|
| - // pthread_cond_wait. So we cannot arrive at a deadlock that will block the
|
| - // main thread.
|
| -
|
| - *read_ahead_array_buffer_ptr_ = array_buffer; // Copy operation.
|
| - available_data_ = true;
|
| -
|
| - pthread_cond_signal(&available_data_cond_);
|
| - }
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -}
|
| -
|
| -void VolumeReaderJavaScriptStream::ReadErrorSignal() {
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - read_error_ = true; // Read error from JavaScript.
|
| - pthread_cond_signal(&available_data_cond_);
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -}
|
| -
|
| -void VolumeReaderJavaScriptStream::SetPassphraseAndSignal(
|
| - const std::string& passphrase) {
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - // Signal VolumeReaderJavaScriptStream::Passphrase to continue execution.
|
| - available_passphrase_ = passphrase;
|
| - pthread_cond_signal(&available_passphrase_cond_);
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -}
|
| -
|
| -void VolumeReaderJavaScriptStream::PassphraseErrorSignal() {
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - passphrase_error_ = true; // Passphrase error from JavaScript.
|
| - pthread_cond_signal(&available_passphrase_cond_);
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -}
|
| -
|
| -int64_t VolumeReaderJavaScriptStream::Read(int64_t bytes_to_read,
|
| - const void** destination_buffer) {
|
| - PP_DCHECK(bytes_to_read > 0);
|
| -
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| -
|
| - // No more data, so signal end of reading.
|
| - if (offset_ >= archive_size_) {
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return 0;
|
| - }
|
| -
|
| - // Call in case of first read or read after Seek and Skip.
|
| - if (last_read_chunk_offset_ != offset_)
|
| - RequestChunk(bytes_to_read);
|
| -
|
| - if (!available_data_) {
|
| - // Wait for data from JavaScript.
|
| - while (!available_data_) { // Check again available data as first call
|
| - // was done outside guarded zone.
|
| - if (read_error_) {
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return ARCHIVE_FATAL;
|
| - }
|
| - pthread_cond_wait(&available_data_cond_, &shared_state_lock_);
|
| - }
|
| - }
|
| -
|
| - if (read_error_) { // Read ahead failed.
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return ARCHIVE_FATAL;
|
| - }
|
| -
|
| - // Make data available for libarchive custom read. No need to lock this part.
|
| - // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only
|
| - // function that can set available_data_ back to false and let
|
| - // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But
|
| - // reading ahead is done only at the end of this function after the buffers
|
| - // are switched.
|
| - *destination_buffer = read_ahead_array_buffer_ptr_->Map();
|
| - int64_t bytes_read =
|
| - std::min(static_cast<int64_t>(read_ahead_array_buffer_ptr_->ByteLength()),
|
| - bytes_to_read);
|
| -
|
| - offset_ += bytes_read;
|
| - last_read_chunk_offset_ = offset_;
|
| -
|
| - // Ask for more data from JavaScript in the other buffer. This is the only
|
| - // time when we switch buffers. The reason is that libarchive must
|
| - // always work on valid data and that data must be available until next
|
| - // VolumeReaderJavaScriptStream::Read call, and as the data can be received
|
| - // at any time from JavaScript, we need a buffer to store it in case of
|
| - // reading ahead.
|
| - read_ahead_array_buffer_ptr_ =
|
| - read_ahead_array_buffer_ptr_ != &first_array_buffer_
|
| - ? &first_array_buffer_
|
| - : &second_array_buffer_;
|
| -
|
| - // Unmap old buffer. Only Read and constructor can Map the buffers so Read and
|
| - // destructor should be the one to Unmap them. This will work because it is
|
| - // called before RequestChunk which is the only method that overwrites the
|
| - // buffer. The constructor should also Map a default pp::VarArrayBuffer and
|
| - // destructor Unmap the last used array buffer (which is the other buffer than
|
| - // read_ahead_array_buffer_ptr_). Unfortunately it's not clear from the
|
| - // API description if this call is done automatically on pp::VarArrayBuffer
|
| - // destructor.
|
| - read_ahead_array_buffer_ptr_->Unmap();
|
| -
|
| - // Read ahead next chunk with a length similar to current read.
|
| - RequestChunk(bytes_to_read);
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -
|
| - return bytes_read;
|
| -}
|
| -
|
| -int64_t VolumeReaderJavaScriptStream::Seek(int64_t offset, int whence) {
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| -
|
| - int64_t new_offset = offset_;
|
| - switch (whence) {
|
| - case SEEK_SET:
|
| - new_offset = offset;
|
| - break;
|
| - case SEEK_CUR:
|
| - new_offset += offset;
|
| - break;
|
| - case SEEK_END:
|
| - new_offset = archive_size_ + offset;
|
| - break;
|
| - default:
|
| - PP_NOTREACHED();
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return ARCHIVE_FATAL;
|
| - }
|
| -
|
| - if (new_offset < 0 || new_offset > archive_size_) {
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return ARCHIVE_FATAL;
|
| - }
|
| -
|
| - offset_ = new_offset;
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -
|
| - return new_offset;
|
| -}
|
| -
|
| -int64_t VolumeReaderJavaScriptStream::Skip(int64_t bytes_to_skip) {
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - // Invalid bytes_to_skip. This "if" can be triggered for corrupted archives.
|
| - // We return 0 instead of ARCHIVE_FATAL in order for libarchive to use normal
|
| - // Read and return the correct error. In case we return ARCHIVE_FATAL here
|
| - // then libarchive just stops without telling us why it wasn't able to
|
| - // process the archive.
|
| - if (archive_size_ - offset_ < bytes_to_skip || bytes_to_skip < 0) {
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return 0;
|
| - }
|
| -
|
| - offset_ += bytes_to_skip;
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -
|
| - return bytes_to_skip;
|
| -}
|
| -
|
| -void VolumeReaderJavaScriptStream::SetRequestId(const std::string& request_id) {
|
| - // No lock necessary, as request_id is used by one thread only.
|
| - request_id_ = request_id;
|
| -}
|
| -
|
| -const char* VolumeReaderJavaScriptStream::Passphrase() {
|
| - // The error is not recoverable. Once passphrase fails to be provided, it is
|
| - // never asked again. Note, that still users are able to retry entering the
|
| - // password, unless they click Cancel.
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - if (passphrase_error_) {
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| - return NULL;
|
| - }
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -
|
| - // Request the passphrase outside of the lock.
|
| - requestor_->RequestPassphrase(request_id_);
|
| -
|
| - pthread_mutex_lock(&shared_state_lock_);
|
| - // Wait for the passphrase from JavaScript.
|
| - pthread_cond_wait(&available_passphrase_cond_, &shared_state_lock_);
|
| - const char* result = NULL;
|
| - if (!passphrase_error_)
|
| - result = strdup(available_passphrase_.c_str());
|
| - pthread_mutex_unlock(&shared_state_lock_);
|
| -
|
| - return result;
|
| -}
|
| -
|
| -void VolumeReaderJavaScriptStream::RequestChunk(int64_t length) {
|
| - // Read next chunk only if not at the end of archive.
|
| - if (archive_size_ <= offset_)
|
| - return;
|
| -
|
| - int64_t bytes_to_read =
|
| - std::min(length, archive_size_ - offset_ /* Positive check above. */);
|
| - available_data_ = false;
|
| -
|
| - requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read);
|
| -}
|
|
|