Index: chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc |
=================================================================== |
--- chrome/browser/media_gallery/mtp_device_delegate_impl_linux.cc (revision 170030) |
+++ 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" |
@@ -353,14 +357,15 @@ |
// Constructed on |media_task_runner_| thread. |
ReadFileWorker(const std::string& handle, |
const std::string& path, |
- uint32 total_size, |
+ uint32 read_offset, |
+ uint32 bytes_to_read, |
SequencedTaskRunner* task_runner, |
WaitableEvent* task_completed_event, |
WaitableEvent* shutdown_event) |
: device_handle_(handle), |
path_(path), |
- total_bytes_(total_size), |
- error_occurred_(false), |
+ read_offset_(read_offset), |
+ bytes_to_read_(bytes_to_read), |
media_task_runner_(task_runner), |
on_task_completed_event_(task_completed_event), |
on_shutdown_event_(shutdown_event) { |
@@ -377,14 +382,12 @@ |
return; |
} |
- while (!error_occurred_ && (data_.size() < total_bytes_) && |
- !cancel_tasks_flag_.IsSet()) { |
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
- Bind(&ReadFileWorker::DoWorkOnUIThread, this)); |
- on_task_completed_event_->Wait(); |
- if (on_shutdown_event_->IsSignaled()) |
kmadhusu
2012/11/29 18:08:17
Instead of moving this logic from ReadFileWorker =
Lei Zhang
2012/11/30 01:01:34
Done.
|
- cancel_tasks_flag_.Set(); |
- } |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ Bind(&ReadFileWorker::DoWorkOnUIThread, this)); |
+ on_task_completed_event_->Wait(); |
+ |
+ if (on_shutdown_event_->IsSignaled()) |
+ cancel_tasks_flag_.Set(); |
} |
// Returns the media file contents received from mtpd. |
@@ -415,7 +418,7 @@ |
return; |
GetMediaTransferProtocolManager()->ReadFileChunkByPath( |
- device_handle_, path_, data_.size(), BytesToRead(), |
+ device_handle_, path_, read_offset_, bytes_to_read_, |
Bind(&ReadFileWorker::OnDidWorkOnUIThread, this)); |
} |
@@ -427,42 +430,25 @@ |
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_ = true; |
- } |
+ DCHECK_EQ(bytes_to_read_, data.size()); |
+ data_ = data; |
} |
on_task_completed_event_->Signal(); |
} |
- 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())); |
- } |
- |
// The device unique identifier to query the device. |
const std::string device_handle_; |
// The media device file path. |
const std::string path_; |
+ const uint32 read_offset_; |
+ const uint32 bytes_to_read_; |
+ |
// The data from mtpd. |
std::string data_; |
- // Number of bytes to read. |
- const uint32 total_bytes_; |
- |
- // Whether an error occurred during file transfer. |
- bool error_occurred_; |
- |
// A reference to |media_task_runner_| to destruct this object on the correct |
// thread. |
scoped_refptr<SequencedTaskRunner> media_task_runner_; |
@@ -857,25 +843,39 @@ |
if (file_info->size <= 0 || file_info->size > kuint32max) |
return base::PLATFORM_FILE_ERROR_FAILED; |
- scoped_refptr<ReadFileWorker> worker(new ReadFileWorker( |
- device_handle_, |
- GetDeviceRelativePath(device_path_, device_file_path.value()), |
- file_info->size, |
- media_task_runner_, &on_task_completed_event_, &on_shutdown_event_)); |
- worker->Run(); |
+ // Read data in 1 MB chunks. |
+ static const uint32 kReadChunkSize = 1024 * 1024; |
+ uint32 bytes_remaining = file_info->size; |
+ int fd = open(local_path.value().c_str(), O_WRONLY); |
+ if (fd < 0) |
+ return base::PLATFORM_FILE_ERROR_FAILED; |
+ file_util::ScopedFD fd_scoper(&fd); |
- 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) { |
- return base::PLATFORM_FILE_ERROR_FAILED; |
+ while (bytes_remaining > 0) { |
+ uint32 offset = file_info->size - bytes_remaining; |
+ uint32 bytes_to_read = std::min(kReadChunkSize, bytes_remaining); |
+ |
+ scoped_refptr<ReadFileWorker> worker(new ReadFileWorker( |
+ device_handle_, |
+ GetDeviceRelativePath(device_path_, device_file_path.value()), |
+ offset, bytes_to_read, |
+ 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 (bytes_to_read != file_data.length() || |
+ file_util::WriteFileDescriptor(fd, file_data.c_str(), data_size) < 0) { |
+ return base::PLATFORM_FILE_ERROR_FAILED; |
+ } |
+ |
+ bytes_remaining -= data_size; |
} |
// 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() { |