Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / media_galleries / linux / mtp_device_task_helper.cc
blob43891abcf91d41cc255e85c8de2ae54cdb869c7f
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"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
13 #include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
14 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
15 #include "components/storage_monitor/storage_monitor.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
18 #include "net/base/io_buffer.h"
19 #include "storage/browser/fileapi/async_file_util.h"
20 #include "storage/common/fileapi/file_system_util.h"
21 #include "third_party/cros_system_api/dbus/service_constants.h"
23 using storage_monitor::StorageMonitor;
25 namespace {
27 // Does nothing.
28 // This method is used to handle the results of
29 // MediaTransferProtocolManager::CloseStorage method call.
30 void DoNothing(bool error) {
33 device::MediaTransferProtocolManager* GetMediaTransferProtocolManager() {
34 return StorageMonitor::GetInstance()->media_transfer_protocol_manager();
37 base::File::Info FileInfoFromMTPFileEntry(const MtpFileEntry& file_entry) {
38 base::File::Info file_entry_info;
39 file_entry_info.size = file_entry.file_size();
40 file_entry_info.is_directory =
41 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER;
42 file_entry_info.is_symbolic_link = false;
43 file_entry_info.last_modified =
44 base::Time::FromTimeT(file_entry.modification_time());
45 file_entry_info.last_accessed = file_entry_info.last_modified;
46 file_entry_info.creation_time = base::Time();
47 return file_entry_info;
50 } // namespace
52 MTPDeviceTaskHelper::MTPDeviceTaskHelper()
53 : weak_ptr_factory_(this) {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
57 MTPDeviceTaskHelper::~MTPDeviceTaskHelper() {
58 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
61 void MTPDeviceTaskHelper::OpenStorage(const std::string& storage_name,
62 const bool read_only,
63 const OpenStorageCallback& callback) {
64 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
65 DCHECK(!storage_name.empty());
66 if (!device_handle_.empty()) {
67 content::BrowserThread::PostTask(content::BrowserThread::IO,
68 FROM_HERE,
69 base::Bind(callback, true));
70 return;
73 const std::string mode =
74 read_only ? mtpd::kReadOnlyMode : mtpd::kReadWriteMode;
75 GetMediaTransferProtocolManager()->OpenStorage(
76 storage_name, mode, base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage,
77 weak_ptr_factory_.GetWeakPtr(), callback));
80 void MTPDeviceTaskHelper::GetFileInfo(
81 uint32 file_id,
82 const GetFileInfoSuccessCallback& success_callback,
83 const ErrorCallback& error_callback) {
84 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
85 if (device_handle_.empty())
86 return HandleDeviceError(error_callback, base::File::FILE_ERROR_FAILED);
88 GetMediaTransferProtocolManager()->GetFileInfo(
89 device_handle_, file_id,
90 base::Bind(&MTPDeviceTaskHelper::OnGetFileInfo,
91 weak_ptr_factory_.GetWeakPtr(),
92 success_callback,
93 error_callback));
96 void MTPDeviceTaskHelper::CreateDirectory(
97 const uint32 parent_id,
98 const std::string& directory_name,
99 const CreateDirectorySuccessCallback& success_callback,
100 const ErrorCallback& error_callback) {
101 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
102 if (device_handle_.empty())
103 return HandleDeviceError(error_callback, base::File::FILE_ERROR_FAILED);
105 GetMediaTransferProtocolManager()->CreateDirectory(
106 device_handle_, parent_id, directory_name,
107 base::Bind(&MTPDeviceTaskHelper::OnCreateDirectory,
108 weak_ptr_factory_.GetWeakPtr(), success_callback,
109 error_callback));
112 void MTPDeviceTaskHelper::ReadDirectory(
113 const uint32 directory_id,
114 const size_t max_size,
115 const ReadDirectorySuccessCallback& success_callback,
116 const ErrorCallback& error_callback) {
117 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
118 if (device_handle_.empty())
119 return HandleDeviceError(error_callback, base::File::FILE_ERROR_FAILED);
121 GetMediaTransferProtocolManager()->ReadDirectory(
122 device_handle_, directory_id, max_size,
123 base::Bind(&MTPDeviceTaskHelper::OnDidReadDirectory,
124 weak_ptr_factory_.GetWeakPtr(), success_callback,
125 error_callback));
128 void MTPDeviceTaskHelper::WriteDataIntoSnapshotFile(
129 const SnapshotRequestInfo& request_info,
130 const base::File::Info& snapshot_file_info) {
131 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
132 if (device_handle_.empty()) {
133 return HandleDeviceError(request_info.error_callback,
134 base::File::FILE_ERROR_FAILED);
137 if (!read_file_worker_)
138 read_file_worker_.reset(new MTPReadFileWorker(device_handle_));
139 read_file_worker_->WriteDataIntoSnapshotFile(request_info,
140 snapshot_file_info);
143 void MTPDeviceTaskHelper::ReadBytes(
144 const MTPDeviceAsyncDelegate::ReadBytesRequest& request) {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
146 if (device_handle_.empty()) {
147 return HandleDeviceError(request.error_callback,
148 base::File::FILE_ERROR_FAILED);
151 GetMediaTransferProtocolManager()->GetFileInfo(
152 device_handle_, request.file_id,
153 base::Bind(&MTPDeviceTaskHelper::OnGetFileInfoToReadBytes,
154 weak_ptr_factory_.GetWeakPtr(), request));
157 void MTPDeviceTaskHelper::RenameObject(
158 const uint32 object_id,
159 const std::string& new_name,
160 const RenameObjectSuccessCallback& success_callback,
161 const ErrorCallback& error_callback) {
162 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
164 GetMediaTransferProtocolManager()->RenameObject(
165 device_handle_, object_id, new_name,
166 base::Bind(&MTPDeviceTaskHelper::OnRenameObject,
167 weak_ptr_factory_.GetWeakPtr(), success_callback,
168 error_callback));
171 // TODO(yawano) storage_name is not used, delete it.
172 void MTPDeviceTaskHelper::CopyFileFromLocal(
173 const std::string& storage_name,
174 const int source_file_descriptor,
175 const uint32 parent_id,
176 const std::string& file_name,
177 const CopyFileFromLocalSuccessCallback& success_callback,
178 const ErrorCallback& error_callback) {
179 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
181 GetMediaTransferProtocolManager()->CopyFileFromLocal(
182 device_handle_, source_file_descriptor, parent_id, file_name,
183 base::Bind(&MTPDeviceTaskHelper::OnCopyFileFromLocal,
184 weak_ptr_factory_.GetWeakPtr(), success_callback,
185 error_callback));
188 void MTPDeviceTaskHelper::DeleteObject(
189 const uint32 object_id,
190 const DeleteObjectSuccessCallback& success_callback,
191 const ErrorCallback& error_callback) {
192 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
194 GetMediaTransferProtocolManager()->DeleteObject(
195 device_handle_, object_id,
196 base::Bind(&MTPDeviceTaskHelper::OnDeleteObject,
197 weak_ptr_factory_.GetWeakPtr(), success_callback,
198 error_callback));
201 void MTPDeviceTaskHelper::CloseStorage() const {
202 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
203 if (device_handle_.empty())
204 return;
205 GetMediaTransferProtocolManager()->CloseStorage(device_handle_,
206 base::Bind(&DoNothing));
209 void MTPDeviceTaskHelper::OnDidOpenStorage(
210 const OpenStorageCallback& completion_callback,
211 const std::string& device_handle,
212 bool error) {
213 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
214 device_handle_ = device_handle;
215 content::BrowserThread::PostTask(content::BrowserThread::IO,
216 FROM_HERE,
217 base::Bind(completion_callback, !error));
220 void MTPDeviceTaskHelper::OnGetFileInfo(
221 const GetFileInfoSuccessCallback& success_callback,
222 const ErrorCallback& error_callback,
223 const MtpFileEntry& file_entry,
224 bool error) const {
225 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
226 if (error) {
227 return HandleDeviceError(error_callback,
228 base::File::FILE_ERROR_NOT_FOUND);
231 content::BrowserThread::PostTask(
232 content::BrowserThread::IO,
233 FROM_HERE,
234 base::Bind(success_callback, FileInfoFromMTPFileEntry(file_entry)));
237 void MTPDeviceTaskHelper::OnCreateDirectory(
238 const CreateDirectorySuccessCallback& success_callback,
239 const ErrorCallback& error_callback,
240 const bool error) const {
241 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
242 if (error) {
243 content::BrowserThread::PostTask(
244 content::BrowserThread::IO, FROM_HERE,
245 base::Bind(error_callback, base::File::FILE_ERROR_FAILED));
246 return;
249 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
250 success_callback);
253 void MTPDeviceTaskHelper::OnDidReadDirectory(
254 const ReadDirectorySuccessCallback& success_callback,
255 const ErrorCallback& error_callback,
256 const std::vector<MtpFileEntry>& file_entries,
257 bool has_more,
258 bool error) const {
259 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
260 if (error)
261 return HandleDeviceError(error_callback, base::File::FILE_ERROR_FAILED);
263 storage::AsyncFileUtil::EntryList entries;
264 base::FilePath current;
265 MTPDeviceObjectEnumerator file_enum(file_entries);
266 while (!(current = file_enum.Next()).empty()) {
267 storage::DirectoryEntry entry;
268 entry.name = storage::VirtualPath::BaseName(current).value();
269 uint32 file_id = 0;
270 bool ret = file_enum.GetEntryId(&file_id);
271 DCHECK(ret);
272 entry.name.push_back(',');
273 entry.name += base::UintToString(file_id);
274 entry.is_directory = file_enum.IsDirectory();
275 entry.size = file_enum.Size();
276 entry.last_modified_time = file_enum.LastModifiedTime();
277 entries.push_back(entry);
279 content::BrowserThread::PostTask(
280 content::BrowserThread::IO,
281 FROM_HERE,
282 base::Bind(success_callback, entries, has_more));
285 void MTPDeviceTaskHelper::OnGetFileInfoToReadBytes(
286 const MTPDeviceAsyncDelegate::ReadBytesRequest& request,
287 const MtpFileEntry& file_entry,
288 bool error) {
289 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
290 DCHECK(request.buf.get());
291 DCHECK_GE(request.buf_len, 0);
292 DCHECK_GE(request.offset, 0);
293 if (error) {
294 return HandleDeviceError(request.error_callback,
295 base::File::FILE_ERROR_FAILED);
298 base::File::Info file_info = FileInfoFromMTPFileEntry(file_entry);
299 if (file_info.is_directory) {
300 return HandleDeviceError(request.error_callback,
301 base::File::FILE_ERROR_NOT_A_FILE);
302 } else if (file_info.size < 0 || file_info.size > kuint32max ||
303 request.offset > file_info.size) {
304 return HandleDeviceError(request.error_callback,
305 base::File::FILE_ERROR_FAILED);
306 } else if (request.offset == file_info.size) {
307 content::BrowserThread::PostTask(content::BrowserThread::IO,
308 FROM_HERE,
309 base::Bind(request.success_callback,
310 file_info, 0u));
311 return;
314 uint32 bytes_to_read = std::min(
315 base::checked_cast<uint32>(request.buf_len),
316 base::saturated_cast<uint32>(file_info.size - request.offset));
318 GetMediaTransferProtocolManager()->ReadFileChunk(
319 device_handle_,
320 request.file_id,
321 base::checked_cast<uint32>(request.offset),
322 bytes_to_read,
323 base::Bind(&MTPDeviceTaskHelper::OnDidReadBytes,
324 weak_ptr_factory_.GetWeakPtr(), request, file_info));
327 void MTPDeviceTaskHelper::OnDidReadBytes(
328 const MTPDeviceAsyncDelegate::ReadBytesRequest& request,
329 const base::File::Info& file_info,
330 const std::string& data,
331 bool error) const {
332 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
333 if (error) {
334 return HandleDeviceError(request.error_callback,
335 base::File::FILE_ERROR_FAILED);
338 CHECK_LE(base::checked_cast<int>(data.length()), request.buf_len);
339 std::copy(data.begin(), data.end(), request.buf->data());
341 content::BrowserThread::PostTask(content::BrowserThread::IO,
342 FROM_HERE,
343 base::Bind(request.success_callback,
344 file_info, data.length()));
347 void MTPDeviceTaskHelper::OnRenameObject(
348 const RenameObjectSuccessCallback& success_callback,
349 const ErrorCallback& error_callback,
350 const bool error) const {
351 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
352 if (error) {
353 content::BrowserThread::PostTask(
354 content::BrowserThread::IO, FROM_HERE,
355 base::Bind(error_callback, base::File::FILE_ERROR_FAILED));
356 return;
359 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
360 success_callback);
363 void MTPDeviceTaskHelper::OnCopyFileFromLocal(
364 const CopyFileFromLocalSuccessCallback& success_callback,
365 const ErrorCallback& error_callback,
366 const bool error) const {
367 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
368 if (error) {
369 content::BrowserThread::PostTask(
370 content::BrowserThread::IO, FROM_HERE,
371 base::Bind(error_callback, base::File::FILE_ERROR_FAILED));
372 return;
375 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
376 success_callback);
379 void MTPDeviceTaskHelper::OnDeleteObject(
380 const DeleteObjectSuccessCallback& success_callback,
381 const ErrorCallback& error_callback,
382 const bool error) const {
383 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
384 if (error) {
385 content::BrowserThread::PostTask(
386 content::BrowserThread::IO, FROM_HERE,
387 base::Bind(error_callback, base::File::FILE_ERROR_FAILED));
388 return;
391 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
392 base::Bind(success_callback));
395 void MTPDeviceTaskHelper::HandleDeviceError(
396 const ErrorCallback& error_callback,
397 base::File::Error error) const {
398 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
399 content::BrowserThread::PostTask(content::BrowserThread::IO,
400 FROM_HERE,
401 base::Bind(error_callback, error));