Chromium Code Reviews| Index: chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc |
| =================================================================== |
| --- chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc (revision 170236) |
| +++ chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc (working copy) |
| @@ -4,6 +4,10 @@ |
| #include "chrome/browser/media_gallery/mtp_device_delegate_impl_linux.h" |
| +#include <fcntl.h> |
| +#include <sys/stat.h> |
| +#include <sys/types.h> |
| + |
| #include "base/bind.h" |
| #include "base/file_path.h" |
| #include "base/file_util.h" |
| @@ -352,14 +356,18 @@ |
| public: |
| // Constructed on |media_task_runner_| thread. |
| ReadFileWorker(const std::string& handle, |
| - const std::string& path, |
| + const std::string& src_path, |
| uint32 total_size, |
| + const FilePath& dest_path, |
| SequencedTaskRunner* task_runner, |
| WaitableEvent* task_completed_event, |
| WaitableEvent* shutdown_event) |
| : device_handle_(handle), |
| - path_(path), |
| + src_path_(src_path), |
| + bytes_read_(0), |
| total_bytes_(total_size), |
| + dest_path_(dest_path), |
| + dest_fd_(-1), |
| error_occurred_(false), |
| media_task_runner_(task_runner), |
| on_task_completed_event_(task_completed_event), |
| @@ -377,18 +385,25 @@ |
| return; |
| } |
| - while (!error_occurred_ && (data_.size() < total_bytes_) && |
| - !cancel_tasks_flag_.IsSet()) { |
| + dest_fd_ = open(dest_path_.value().c_str(), O_WRONLY); |
| + if (dest_fd_ < 0) |
| + return; |
| + dest_fd_scoper_.reset(&dest_fd_); |
| + |
| + while (!error_occurred_ && (bytes_read_ < total_bytes_)) { |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| Bind(&ReadFileWorker::DoWorkOnUIThread, this)); |
| on_task_completed_event_->Wait(); |
| - if (on_shutdown_event_->IsSignaled()) |
| + if (on_shutdown_event_->IsSignaled()) { |
| cancel_tasks_flag_.Set(); |
| + break; |
| + } |
| } |
| } |
| - // Returns the media file contents received from mtpd. |
| - const std::string& data() const { return data_; } |
| + bool Succeeded() const { |
| + return !error_occurred_ && bytes_read_ == total_bytes_; |
| + } |
| // Returns the |media_task_runner_| associated with this worker object. |
| // This function is exposed for WorkerDeleter struct to access the |
| @@ -415,7 +430,7 @@ |
| return; |
| GetMediaTransferProtocolManager()->ReadFileChunkByPath( |
| - device_handle_, path_, data_.size(), BytesToRead(), |
| + device_handle_, src_path_, bytes_read_, BytesToRead(), |
| Bind(&ReadFileWorker::OnDidWorkOnUIThread, this)); |
| } |
| @@ -427,16 +442,14 @@ |
| if (cancel_tasks_flag_.IsSet()) |
| return; |
| - error_occurred_ = error; |
| - if (!error) { |
| - if ((BytesToRead() == data.size())) { |
| - // TODO(kmadhusu): Data could be really huge. Consider passing data by |
| - // pointer/ref rather than by value here to avoid an extra data copy. |
| - data_.append(data); |
| - } else { |
| - NOTREACHED(); |
| + error_occurred_ = error || (data.size() != BytesToRead()); |
| + if (!error_occurred_) { |
| + int bytes_written = |
| + file_util::WriteFileDescriptor(dest_fd_, data.data(), data.size()); |
|
kmadhusu
2012/11/30 01:13:09
You are trying to do a file write operation on a U
|
| + if (static_cast<int>(data.size()) == bytes_written) |
| + bytes_read_ += data.size(); |
| + else |
| error_occurred_ = true; |
| - } |
| } |
| on_task_completed_event_->Signal(); |
| } |
| @@ -444,22 +457,30 @@ |
| uint32 BytesToRead() const { |
| // Read data in 1 MB chunks. |
| static const uint32 kReadChunkSize = 1024 * 1024; |
| - return std::min(kReadChunkSize, |
| - total_bytes_ - static_cast<uint32>(data_.size())); |
| + return std::min(kReadChunkSize, total_bytes_ - bytes_read_); |
| } |
| // The device unique identifier to query the device. |
| const std::string device_handle_; |
| // The media device file path. |
| - const std::string path_; |
| + const std::string src_path_; |
| - // The data from mtpd. |
| - std::string data_; |
| + // Number of bytes read from the device. |
| + uint32 bytes_read_; |
| // Number of bytes to read. |
| const uint32 total_bytes_; |
| + // Where to write the data read from the device. |
| + const FilePath dest_path_; |
| + |
| + // File descriptor for |dest_path_|. |
| + int dest_fd_; |
| + |
| + // Scoper to cleanup |dest_fd_|. |
| + file_util::ScopedFD dest_fd_scoper_; |
| + |
| // Whether an error occurred during file transfer. |
| bool error_occurred_; |
| @@ -860,22 +881,17 @@ |
| scoped_refptr<ReadFileWorker> worker(new ReadFileWorker( |
| device_handle_, |
| GetDeviceRelativePath(device_path_, device_file_path.value()), |
| - file_info->size, |
| + file_info->size, local_path, |
| media_task_runner_, &on_task_completed_event_, &on_shutdown_event_)); |
| worker->Run(); |
| - const std::string& file_data = worker->data(); |
| - int data_size = static_cast<int>(file_data.length()); |
| - if (file_data.empty() || |
| - file_util::WriteFile(local_path, file_data.c_str(), |
| - data_size) != data_size) { |
| + if (!worker->Succeeded()) |
| return base::PLATFORM_FILE_ERROR_FAILED; |
| - } |
| // Modify the last modified time to null. This prevents the time stamp |
| // verfication in LocalFileStreamReader. |
| file_info->last_modified = base::Time(); |
| - return error; |
| + return base::PLATFORM_FILE_OK; |
| } |
| SequencedTaskRunner* MTPDeviceDelegateImplLinux::GetMediaTaskRunner() { |