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