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 "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"
21 // This method is used to handle the results of
22 // MediaTransferProtocolManager::CloseStorage method call.
23 void DoNothing(bool error) {
26 device::MediaTransferProtocolManager* GetMediaTransferProtocolManager() {
27 return StorageMonitor::GetInstance()->media_transfer_protocol_manager();
32 MTPDeviceTaskHelper::MTPDeviceTaskHelper()
33 : weak_ptr_factory_(this) {
34 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
37 MTPDeviceTaskHelper::~MTPDeviceTaskHelper() {
38 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
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,
48 base::Bind(callback, true));
51 GetMediaTransferProtocolManager()->OpenStorage(
52 storage_name, mtpd::kReadOnlyMode,
53 base::Bind(&MTPDeviceTaskHelper::OnDidOpenStorage,
54 weak_ptr_factory_.GetWeakPtr(),
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);
66 GetMediaTransferProtocolManager()->GetFileInfoByPath(
67 device_handle_, file_path,
68 base::Bind(&MTPDeviceTaskHelper::OnGetFileInfo,
69 weak_ptr_factory_.GetWeakPtr(),
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);
82 GetMediaTransferProtocolManager()->ReadDirectoryByPath(
83 device_handle_, dir_path,
84 base::Bind(&MTPDeviceTaskHelper::OnDidReadDirectoryByPath,
85 weak_ptr_factory_.GetWeakPtr(),
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);
99 if (!read_file_worker_)
100 read_file_worker_.reset(new MTPReadFileWorker(device_handle_));
101 read_file_worker_->WriteDataIntoSnapshotFile(request_info,
105 void MTPDeviceTaskHelper::CloseStorage() const {
106 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
107 if (device_handle_.empty())
109 GetMediaTransferProtocolManager()->CloseStorage(device_handle_,
110 base::Bind(&DoNothing));
113 void MTPDeviceTaskHelper::OnDidOpenStorage(
114 const OpenStorageCallback& completion_callback,
115 const std::string& device_handle,
117 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
118 device_handle_ = device_handle;
119 content::BrowserThread::PostTask(content::BrowserThread::IO,
121 base::Bind(completion_callback, !error));
124 void MTPDeviceTaskHelper::OnGetFileInfo(
125 const GetFileInfoSuccessCallback& success_callback,
126 const ErrorCallback& error_callback,
127 const MtpFileEntry& file_entry,
129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
131 return HandleDeviceError(error_callback,
132 base::PLATFORM_FILE_ERROR_NOT_FOUND);
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,
146 base::Bind(success_callback,
150 void MTPDeviceTaskHelper::OnDidReadDirectoryByPath(
151 const ReadDirectorySuccessCallback& success_callback,
152 const ErrorCallback& error_callback,
153 const std::vector<MtpFileEntry>& file_entries,
155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
157 return HandleDeviceError(error_callback, base::PLATFORM_FILE_ERROR_FAILED);
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);
170 content::BrowserThread::PostTask(content::BrowserThread::IO,
172 base::Bind(success_callback, entries));
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,
181 base::Bind(error_callback, error));