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. 4 5 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h" 9 #include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h" 10 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" 11 #include "chrome/browser/storage_monitor/storage_monitor.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h" 14 #include "third_party/cros_system_api/dbus/service_constants.h" 15 #include "webkit/browser/fileapi/async_file_util.h" 16 #include "webkit/common/fileapi/file_system_util.h" 17 18 namespace { 19 20 // Does nothing. 21 // This method is used to handle the results of 22 // MediaTransferProtocolManager::CloseStorage method call. 23 void DoNothing(bool error) { 24 } 25 26 device::MediaTransferProtocolManager* GetMediaTransferProtocolManager() { 27 return StorageMonitor::GetInstance()->media_transfer_protocol_manager(); 28 } 29 30 } // namespace 31 32 MTPDeviceTaskHelper::MTPDeviceTaskHelper() 33 : weak_ptr_factory_(this) { 34 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 35 } 36 37 MTPDeviceTaskHelper::~MTPDeviceTaskHelper() { 38 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 39 } 40 41 void MTPDeviceTaskHelper::OpenStorage(const std::string& storage_name, 42 const OpenStorageCallback& callback) { 43 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 44 DCHECK(!storage_name.empty()); 45 if (!device_handle_.empty()) { 46 content::BrowserThread::PostTask(content::BrowserThread::IO, 47 FROM_HERE, 48 base::Bind(callback, true)); 49 return; 50 } 51 GetMediaTransferProtocolManager()->OpenStorage( 52 storage_name, mtpd::kReadOnlyMode, 53 base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage, 54 weak_ptr_factory_.GetWeakPtr(), 55 callback)); 56 } 57 58 void MTPDeviceTaskHelper::GetFileInfoByPath( 59 const std::string& file_path, 60 const GetFileInfoSuccessCallback& success_callback, 61 const ErrorCallback& error_callback) { 62 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 63 if (device_handle_.empty()) 64 return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED); 65 66 GetMediaTransferProtocolManager()->GetFileInfoByPath( 67 device_handle_, file_path, 68 base::Bind(&MTPDeviceTaskHelper::OnGetFileInfo, 69 weak_ptr_factory_.GetWeakPtr(), 70 success_callback, 71 error_callback)); 72 } 73 74 void MTPDeviceTaskHelper::ReadDirectoryByPath( 75 const std::string& dir_path, 76 const ReadDirectorySuccessCallback& success_callback, 77 const ErrorCallback& error_callback) { 78 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 79 if (device_handle_.empty()) 80 return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED); 81 82 GetMediaTransferProtocolManager()->ReadDirectoryByPath( 83 device_handle_, dir_path, 84 base::Bind(&MTPDeviceTaskHelper::OnDidReadDirectoryByPath, 85 weak_ptr_factory_.GetWeakPtr(), 86 success_callback, 87 error_callback)); 88 } 89 90 void MTPDeviceTaskHelper::WriteDataIntoSnapshotFile( 91 const SnapshotRequestInfo& request_info, 92 const base::PlatformFileInfo& snapshot_file_info) { 93 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 94 if (device_handle_.empty()) { 95 return HandleDeviceError(request_info.error_callback, 96 base::PLATFORM_FILE_ERROR_FAILED); 97 } 98 99 if (!read_file_worker_) 100 read_file_worker_.reset(new MTPReadFileWorker(device_handle_)); 101 read_file_worker_->WriteDataIntoSnapshotFile(request_info, 102 snapshot_file_info); 103 } 104 105 void MTPDeviceTaskHelper::CloseStorage() const { 106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 107 if (device_handle_.empty()) 108 return; 109 GetMediaTransferProtocolManager()->CloseStorage(device_handle_, 110 base::Bind(&DoNothing)); 111 } 112 113 void MTPDeviceTaskHelper::OnDidOpenStorage( 114 const OpenStorageCallback& completion_callback, 115 const std::string& device_handle, 116 bool error) { 117 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 118 device_handle_ = device_handle; 119 content::BrowserThread::PostTask(content::BrowserThread::IO, 120 FROM_HERE, 121 base::Bind(completion_callback, !error)); 122 } 123 124 void MTPDeviceTaskHelper::OnGetFileInfo( 125 const GetFileInfoSuccessCallback& success_callback, 126 const ErrorCallback& error_callback, 127 const MtpFileEntry& file_entry, 128 bool error) const { 129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 130 if (error) { 131 return HandleDeviceError(error_callback, 132 base::PLATFORM_FILE_ERROR_NOT_FOUND); 133 } 134 135 base::PlatformFileInfo file_entry_info; 136 file_entry_info.size = file_entry.file_size(); 137 file_entry_info.is_directory = 138 file_entry.file_type() == MtpFileEntry::FILE_TYPE_FOLDER; 139 file_entry_info.is_symbolic_link = false; 140 file_entry_info.last_modified = 141 base::Time::FromTimeT(file_entry.modification_time()); 142 file_entry_info.last_accessed = file_entry_info.last_modified; 143 file_entry_info.creation_time = base::Time(); 144 content::BrowserThread::PostTask(content::BrowserThread::IO, 145 FROM_HERE, 146 base::Bind(success_callback, 147 file_entry_info)); 148 } 149 150 void MTPDeviceTaskHelper::OnDidReadDirectoryByPath( 151 const ReadDirectorySuccessCallback& success_callback, 152 const ErrorCallback& error_callback, 153 const std::vector<MtpFileEntry>& file_entries, 154 bool error) const { 155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 156 if (error) 157 return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED); 158 159 fileapi::AsyncFileUtil::EntryList entries; 160 base::FilePath current; 161 MTPDeviceObjectEnumerator file_enum(file_entries); 162 while (!(current = file_enum.Next()).empty()) { 163 fileapi::DirectoryEntry entry; 164 entry.name = fileapi::VirtualPath::BaseName(current).value(); 165 entry.is_directory = file_enum.IsDirectory(); 166 entry.size = file_enum.Size(); 167 entry.last_modified_time = file_enum.LastModifiedTime(); 168 entries.push_back(entry); 169 } 170 content::BrowserThread::PostTask(content::BrowserThread::IO, 171 FROM_HERE, 172 base::Bind(success_callback, entries)); 173 } 174 175 void MTPDeviceTaskHelper::HandleDeviceError( 176 const ErrorCallback& error_callback, 177 base::PlatformFileError error) const { 178 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 179 content::BrowserThread::PostTask(content::BrowserThread::IO, 180 FROM_HERE, 181 base::Bind(error_callback, error)); 182 } 183