1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
12 #include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
13 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
14 #include "chrome/browser/storage_monitor/storage_monitor.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
17 #include "net/base/io_buffer.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19 #include "webkit/browser/fileapi/async_file_util.h"
20 #include "webkit/common/fileapi/file_system_util.h"
25 // This method is used to handle the results of
26 // MediaTransferProtocolManager::CloseStorage method call.
27 void DoNothing(bool error
) {
30 device::MediaTransferProtocolManager
* GetMediaTransferProtocolManager() {
31 return StorageMonitor::GetInstance()->media_transfer_protocol_manager();
36 MTPDeviceTaskHelper::MTPDeviceTaskHelper()
37 : weak_ptr_factory_(this) {
38 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
41 MTPDeviceTaskHelper::~MTPDeviceTaskHelper() {
42 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
45 void MTPDeviceTaskHelper::OpenStorage(const std::string
& storage_name
,
46 const OpenStorageCallback
& callback
) {
47 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
48 DCHECK(!storage_name
.empty());
49 if (!device_handle_
.empty()) {
50 content::BrowserThread::PostTask(content::BrowserThread::IO
,
52 base::Bind(callback
, true));
55 GetMediaTransferProtocolManager()->OpenStorage(
56 storage_name
, mtpd::kReadOnlyMode
,
57 base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage
,
58 weak_ptr_factory_
.GetWeakPtr(),
62 void MTPDeviceTaskHelper::GetFileInfoByPath(
63 const std::string
& file_path
,
64 const GetFileInfoSuccessCallback
& success_callback
,
65 const ErrorCallback
& error_callback
) {
66 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
67 if (device_handle_
.empty())
68 return HandleDeviceError(error_callback
, base::File::FILE_ERROR_FAILED
);
70 GetMediaTransferProtocolManager()->GetFileInfoByPath(
71 device_handle_
, file_path
,
72 base::Bind(&MTPDeviceTaskHelper::OnGetFileInfo
,
73 weak_ptr_factory_
.GetWeakPtr(),
78 void MTPDeviceTaskHelper::ReadDirectoryByPath(
79 const std::string
& dir_path
,
80 const ReadDirectorySuccessCallback
& success_callback
,
81 const ErrorCallback
& error_callback
) {
82 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
83 if (device_handle_
.empty())
84 return HandleDeviceError(error_callback
, base::File::FILE_ERROR_FAILED
);
86 GetMediaTransferProtocolManager()->ReadDirectoryByPath(
87 device_handle_
, dir_path
,
88 base::Bind(&MTPDeviceTaskHelper::OnDidReadDirectoryByPath
,
89 weak_ptr_factory_
.GetWeakPtr(),
94 void MTPDeviceTaskHelper::WriteDataIntoSnapshotFile(
95 const SnapshotRequestInfo
& request_info
,
96 const base::File::Info
& snapshot_file_info
) {
97 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
98 if (device_handle_
.empty()) {
99 return HandleDeviceError(request_info
.error_callback
,
100 base::File::FILE_ERROR_FAILED
);
103 if (!read_file_worker_
)
104 read_file_worker_
.reset(new MTPReadFileWorker(device_handle_
));
105 read_file_worker_
->WriteDataIntoSnapshotFile(request_info
,
109 void MTPDeviceTaskHelper::ReadBytes(
110 const MTPDeviceAsyncDelegate::ReadBytesRequest
& request
) {
111 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
112 if (device_handle_
.empty()) {
113 return HandleDeviceError(request
.error_callback
,
114 base::File::FILE_ERROR_FAILED
);
117 GetMediaTransferProtocolManager()->ReadFileChunkByPath(
119 request
.device_file_relative_path
,
120 base::checked_cast
<uint32
>(request
.offset
),
121 base::checked_cast
<uint32
>(request
.buf_len
),
122 base::Bind(&MTPDeviceTaskHelper::OnDidReadBytes
,
123 weak_ptr_factory_
.GetWeakPtr(), request
));
126 void MTPDeviceTaskHelper::CloseStorage() const {
127 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
128 if (device_handle_
.empty())
130 GetMediaTransferProtocolManager()->CloseStorage(device_handle_
,
131 base::Bind(&DoNothing
));
134 void MTPDeviceTaskHelper::OnDidOpenStorage(
135 const OpenStorageCallback
& completion_callback
,
136 const std::string
& device_handle
,
138 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
139 device_handle_
= device_handle
;
140 content::BrowserThread::PostTask(content::BrowserThread::IO
,
142 base::Bind(completion_callback
, !error
));
145 void MTPDeviceTaskHelper::OnGetFileInfo(
146 const GetFileInfoSuccessCallback
& success_callback
,
147 const ErrorCallback
& error_callback
,
148 const MtpFileEntry
& file_entry
,
150 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
152 return HandleDeviceError(error_callback
,
153 base::File::FILE_ERROR_NOT_FOUND
);
156 base::File::Info file_entry_info
;
157 file_entry_info
.size
= file_entry
.file_size();
158 file_entry_info
.is_directory
=
159 file_entry
.file_type() == MtpFileEntry::FILE_TYPE_FOLDER
;
160 file_entry_info
.is_symbolic_link
= false;
161 file_entry_info
.last_modified
=
162 base::Time::FromTimeT(file_entry
.modification_time());
163 file_entry_info
.last_accessed
= file_entry_info
.last_modified
;
164 file_entry_info
.creation_time
= base::Time();
165 content::BrowserThread::PostTask(content::BrowserThread::IO
,
167 base::Bind(success_callback
,
171 void MTPDeviceTaskHelper::OnDidReadDirectoryByPath(
172 const ReadDirectorySuccessCallback
& success_callback
,
173 const ErrorCallback
& error_callback
,
174 const std::vector
<MtpFileEntry
>& file_entries
,
176 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
178 return HandleDeviceError(error_callback
, base::File::FILE_ERROR_FAILED
);
180 fileapi::AsyncFileUtil::EntryList entries
;
181 base::FilePath current
;
182 MTPDeviceObjectEnumerator
file_enum(file_entries
);
183 while (!(current
= file_enum
.Next()).empty()) {
184 fileapi::DirectoryEntry entry
;
185 entry
.name
= fileapi::VirtualPath::BaseName(current
).value();
186 entry
.is_directory
= file_enum
.IsDirectory();
187 entry
.size
= file_enum
.Size();
188 entry
.last_modified_time
= file_enum
.LastModifiedTime();
189 entries
.push_back(entry
);
191 content::BrowserThread::PostTask(content::BrowserThread::IO
,
193 base::Bind(success_callback
, entries
));
196 void MTPDeviceTaskHelper::OnDidReadBytes(
197 const MTPDeviceAsyncDelegate::ReadBytesRequest
& request
,
198 const std::string
& data
,
200 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
202 return HandleDeviceError(request
.error_callback
,
203 base::File::FILE_ERROR_FAILED
);
206 CHECK_LE(base::checked_cast
<int>(data
.length()), request
.buf_len
);
207 std::copy(data
.begin(), data
.end(), request
.buf
->data());
209 content::BrowserThread::PostTask(content::BrowserThread::IO
,
211 base::Bind(request
.success_callback
,
215 void MTPDeviceTaskHelper::HandleDeviceError(
216 const ErrorCallback
& error_callback
,
217 base::File::Error error
) const {
218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
219 content::BrowserThread::PostTask(content::BrowserThread::IO
,
221 base::Bind(error_callback
, error
));