1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ 6 #define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ 7 8 #include <queue> 9 10 #include "base/callback.h" 11 #include "base/location.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/platform_file.h" 15 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" 16 #include "chrome/browser/media_galleries/mtp_device_delegate_impl.h" 17 #include "webkit/browser/fileapi/async_file_util.h" 18 19 namespace base { 20 class FilePath; 21 } 22 23 namespace chrome { 24 25 struct SnapshotRequestInfo; 26 27 // MTPDeviceDelegateImplLinux communicates with the media transfer protocol 28 // (MTP) device to complete file system operations. These operations are 29 // performed asynchronously. Instantiate this class per MTP device storage. 30 // MTPDeviceDelegateImplLinux lives on the IO thread. 31 // MTPDeviceDelegateImplLinux does a call-and-reply to the UI thread 32 // to dispatch the requests to MediaTransferProtocolManager. 33 class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { 34 private: 35 friend void CreateMTPDeviceAsyncDelegate( 36 const std::string&, 37 const CreateMTPDeviceAsyncDelegateCallback&); 38 39 enum InitializationState { 40 UNINITIALIZED = 0, 41 PENDING_INIT, 42 INITIALIZED 43 }; 44 45 // Used to represent pending task details. 46 struct PendingTaskInfo { 47 PendingTaskInfo(const tracked_objects::Location& location, 48 const base::Closure& task); 49 ~PendingTaskInfo(); 50 51 const tracked_objects::Location location; 52 const base::Closure task; 53 }; 54 55 // Should only be called by CreateMTPDeviceAsyncDelegate() factory call. 56 // Defer the device initializations until the first file operation request. 57 // Do all the initializations in EnsureInitAndRunTask() function. 58 explicit MTPDeviceDelegateImplLinux(const std::string& device_location); 59 60 // Destructed via CancelPendingTasksAndDeleteDelegate(). 61 virtual ~MTPDeviceDelegateImplLinux(); 62 63 // MTPDeviceAsyncDelegate: 64 virtual void GetFileInfo(const base::FilePath& file_path, 65 const GetFileInfoSuccessCallback& success_callback, 66 const ErrorCallback& error_callback) OVERRIDE; 67 virtual void ReadDirectory( 68 const base::FilePath& root, 69 const ReadDirectorySuccessCallback& success_callback, 70 const ErrorCallback& error_callback) OVERRIDE; 71 virtual void CreateSnapshotFile( 72 const base::FilePath& device_file_path, 73 const base::FilePath& local_path, 74 const CreateSnapshotFileSuccessCallback& success_callback, 75 const ErrorCallback& error_callback) OVERRIDE; 76 virtual void CancelPendingTasksAndDeleteDelegate() OVERRIDE; 77 78 // Ensures the device is initialized for communication by doing a 79 // call-and-reply to the UI thread. |task_info.task| runs on the UI thread. 80 // 81 // If the device is already initialized, post the |task_info.task| immediately 82 // on the UI thread. 83 // 84 // If the device is uninitialized, store the |task_info| in a pending task 85 // list and runs all the pending tasks once the device is successfully 86 // initialized. 87 void EnsureInitAndRunTask(const PendingTaskInfo& task_info); 88 89 // Writes data from the device to the snapshot file path based on the 90 // parameters in |current_snapshot_request_info_| by doing a call-and-reply to 91 // the UI thread. 92 // 93 // |snapshot_file_info| specifies the metadata details of the snapshot file. 94 void WriteDataIntoSnapshotFile( 95 const base::PlatformFileInfo& snapshot_file_info); 96 97 // Processes the next pending request. 98 void ProcessNextPendingRequest(); 99 100 // Handles the device initialization event. |succeeded| indicates whether 101 // device initialization succeeded. 102 // 103 // If the device is successfully initialized, runs the next pending task. 104 void OnInitCompleted(bool succeeded); 105 106 // Called when GetFileInfo() succeeds. |file_info| specifies the 107 // requested file details. |success_callback| is invoked to notify the caller 108 // about the requested file details. 109 void OnDidGetFileInfo(const GetFileInfoSuccessCallback& success_callback, 110 const base::PlatformFileInfo& file_info); 111 112 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to 113 // get the |root| directory metadata details. |file_info| specifies the |root| 114 // directory details. 115 // 116 // If |root| is a directory, post a task on the UI thread to read the |root| 117 // directory file entries. 118 // 119 // If |root| is not a directory, |error_callback| is invoked to notify the 120 // caller about the platform file error and process the next pending request. 121 void OnDidGetFileInfoToReadDirectory( 122 const std::string& root, 123 const ReadDirectorySuccessCallback& success_callback, 124 const ErrorCallback& error_callback, 125 const base::PlatformFileInfo& file_info); 126 127 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to 128 // create the snapshot file of |snapshot_request_info.device_file_path|. 129 // |file_info| specifies the device file metadata details. 130 // 131 // Posts a task on the UI thread to copy the data contents of the device file 132 // to the snapshot file. 133 void OnDidGetFileInfoToCreateSnapshotFile( 134 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, 135 const base::PlatformFileInfo& file_info); 136 137 // Called when ReadDirectory() succeeds. 138 // 139 // |file_list| contains the directory file entries. 140 // |success_callback| is invoked to notify the caller about the directory 141 // file entries. 142 void OnDidReadDirectory(const ReadDirectorySuccessCallback& success_callback, 143 const fileapi::AsyncFileUtil::EntryList& file_list); 144 145 // Called when WriteDataIntoSnapshotFile() succeeds. 146 // 147 // |snapshot_file_info| specifies the snapshot file metadata details. 148 // 149 // |current_snapshot_request_info_.success_callback| is invoked to notify the 150 // caller about |snapshot_file_info|. 151 void OnDidWriteDataIntoSnapshotFile( 152 const base::PlatformFileInfo& snapshot_file_info, 153 const base::FilePath& snapshot_file_path); 154 155 // Called when WriteDataIntoSnapshotFile() fails. 156 // 157 // |error| specifies the platform file error code. 158 // 159 // |current_snapshot_request_info_.error_callback| is invoked to notify the 160 // caller about |error|. 161 void OnWriteDataIntoSnapshotFileError(base::PlatformFileError error); 162 163 // Handles the device file |error|. |error_callback| is invoked to notify the 164 // caller about the file error. 165 void HandleDeviceFileError(const ErrorCallback& error_callback, 166 base::PlatformFileError error); 167 168 // MTP device initialization state. 169 InitializationState init_state_; 170 171 // Used to make sure only one task is in progress at any time. 172 bool task_in_progress_; 173 174 // Registered file system device path. This path does not 175 // correspond to a real device path (e.g. "/usb:2,2:81282"). 176 const base::FilePath device_path_; 177 178 // MTP device storage name (e.g. "usb:2,2:81282"). 179 std::string storage_name_; 180 181 // A list of pending tasks that needs to be run when the device is 182 // initialized or when the current task in progress is complete. 183 std::queue<PendingTaskInfo> pending_tasks_; 184 185 // Used to track the current snapshot file request. A snapshot file is created 186 // incrementally. CreateSnapshotFile request reads the device file and writes 187 // to the snapshot file in chunks. In order to retain the order of the 188 // snapshot file requests, make sure there is only one active snapshot file 189 // request at any time. 190 scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_; 191 192 // For callbacks that may run after destruction. 193 base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_; 194 195 DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux); 196 }; 197 198 } // namespace chrome 199 200 #endif // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ 201