OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ | 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_ | 6 #define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ |
7 | 7 |
8 #include <queue> | 8 #include <deque> |
| 9 #include <map> |
| 10 #include <string> |
9 | 11 |
10 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/containers/scoped_ptr_hash_map.h" |
| 14 #include "base/files/file_path.h" |
11 #include "base/location.h" | 15 #include "base/location.h" |
12 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
13 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/weak_ptr.h" |
14 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" | 18 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" |
| 19 #include "content/public/browser/browser_thread.h" |
15 #include "webkit/browser/fileapi/async_file_util.h" | 20 #include "webkit/browser/fileapi/async_file_util.h" |
16 | 21 |
17 namespace base { | |
18 class FilePath; | |
19 } | |
20 | |
21 struct SnapshotRequestInfo; | 22 struct SnapshotRequestInfo; |
22 | 23 |
23 // MTPDeviceDelegateImplLinux communicates with the media transfer protocol | 24 // MTPDeviceDelegateImplLinux communicates with the media transfer protocol |
24 // (MTP) device to complete file system operations. These operations are | 25 // (MTP) device to complete file system operations. These operations are |
25 // performed asynchronously. Instantiate this class per MTP device storage. | 26 // performed asynchronously. Instantiate this class per MTP device storage. |
26 // MTPDeviceDelegateImplLinux lives on the IO thread. | 27 // MTPDeviceDelegateImplLinux lives on the IO thread. |
27 // MTPDeviceDelegateImplLinux does a call-and-reply to the UI thread | 28 // MTPDeviceDelegateImplLinux does a call-and-reply to the UI thread |
28 // to dispatch the requests to MediaTransferProtocolManager. | 29 // to dispatch the requests to MediaTransferProtocolManager. |
29 class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { | 30 class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { |
30 private: | 31 private: |
31 friend void CreateMTPDeviceAsyncDelegate( | 32 friend void CreateMTPDeviceAsyncDelegate( |
32 const std::string&, | 33 const std::string&, |
33 const CreateMTPDeviceAsyncDelegateCallback&); | 34 const CreateMTPDeviceAsyncDelegateCallback&); |
34 | 35 |
35 enum InitializationState { | 36 enum InitializationState { |
36 UNINITIALIZED = 0, | 37 UNINITIALIZED = 0, |
37 PENDING_INIT, | 38 PENDING_INIT, |
38 INITIALIZED | 39 INITIALIZED |
39 }; | 40 }; |
40 | 41 |
41 // Used to represent pending task details. | 42 // Used to represent pending task details. |
42 struct PendingTaskInfo { | 43 struct PendingTaskInfo { |
43 PendingTaskInfo(const tracked_objects::Location& location, | 44 PendingTaskInfo(const base::FilePath& path, |
| 45 content::BrowserThread::ID thread_id, |
| 46 const tracked_objects::Location& location, |
44 const base::Closure& task); | 47 const base::Closure& task); |
45 ~PendingTaskInfo(); | 48 ~PendingTaskInfo(); |
46 | 49 |
| 50 base::FilePath path; |
| 51 base::FilePath cached_path; |
| 52 const content::BrowserThread::ID thread_id; |
47 const tracked_objects::Location location; | 53 const tracked_objects::Location location; |
48 const base::Closure task; | 54 const base::Closure task; |
49 }; | 55 }; |
50 | 56 |
| 57 class MTPFileNode; |
| 58 |
| 59 // Maps file ids to file nodes. |
| 60 typedef std::map<uint32, MTPFileNode*> FileIdToMTPFileNodeMap; |
| 61 |
51 // Should only be called by CreateMTPDeviceAsyncDelegate() factory call. | 62 // Should only be called by CreateMTPDeviceAsyncDelegate() factory call. |
52 // Defer the device initializations until the first file operation request. | 63 // Defer the device initializations until the first file operation request. |
53 // Do all the initializations in EnsureInitAndRunTask() function. | 64 // Do all the initializations in EnsureInitAndRunTask() function. |
54 explicit MTPDeviceDelegateImplLinux(const std::string& device_location); | 65 explicit MTPDeviceDelegateImplLinux(const std::string& device_location); |
55 | 66 |
56 // Destructed via CancelPendingTasksAndDeleteDelegate(). | 67 // Destructed via CancelPendingTasksAndDeleteDelegate(). |
57 virtual ~MTPDeviceDelegateImplLinux(); | 68 virtual ~MTPDeviceDelegateImplLinux(); |
58 | 69 |
59 // MTPDeviceAsyncDelegate: | 70 // MTPDeviceAsyncDelegate: |
60 virtual void GetFileInfo(const base::FilePath& file_path, | 71 virtual void GetFileInfo(const base::FilePath& file_path, |
61 const GetFileInfoSuccessCallback& success_callback, | 72 const GetFileInfoSuccessCallback& success_callback, |
62 const ErrorCallback& error_callback) OVERRIDE; | 73 const ErrorCallback& error_callback) OVERRIDE; |
63 virtual void ReadDirectory( | 74 virtual void ReadDirectory( |
64 const base::FilePath& root, | 75 const base::FilePath& root, |
65 const ReadDirectorySuccessCallback& success_callback, | 76 const ReadDirectorySuccessCallback& success_callback, |
66 const ErrorCallback& error_callback) OVERRIDE; | 77 const ErrorCallback& error_callback) OVERRIDE; |
67 virtual void CreateSnapshotFile( | 78 virtual void CreateSnapshotFile( |
68 const base::FilePath& device_file_path, | 79 const base::FilePath& device_file_path, |
69 const base::FilePath& local_path, | 80 const base::FilePath& local_path, |
70 const CreateSnapshotFileSuccessCallback& success_callback, | 81 const CreateSnapshotFileSuccessCallback& success_callback, |
71 const ErrorCallback& error_callback) OVERRIDE; | 82 const ErrorCallback& error_callback) OVERRIDE; |
72 virtual bool IsStreaming() OVERRIDE; | 83 virtual bool IsStreaming() OVERRIDE; |
73 virtual void ReadBytes( | 84 virtual void ReadBytes( |
74 const base::FilePath& device_file_path, | 85 const base::FilePath& device_file_path, |
75 net::IOBuffer* buf, int64 offset, int buf_len, | 86 net::IOBuffer* buf, int64 offset, int buf_len, |
76 const ReadBytesSuccessCallback& success_callback, | 87 const ReadBytesSuccessCallback& success_callback, |
77 const ErrorCallback& error_callback) OVERRIDE; | 88 const ErrorCallback& error_callback) OVERRIDE; |
78 virtual void CancelPendingTasksAndDeleteDelegate() OVERRIDE; | 89 virtual void CancelPendingTasksAndDeleteDelegate() OVERRIDE; |
79 | 90 |
80 // Ensures the device is initialized for communication by doing a | 91 // The internal methods correspond to the similarly named methods above. |
81 // call-and-reply to the UI thread. |task_info.task| runs on the UI thread. | 92 // The |root_node_| cache should be filled at this point. |
82 // | 93 virtual void GetFileInfoInternal( |
83 // If the device is already initialized, post the |task_info.task| immediately | 94 const base::FilePath& file_path, |
84 // on the UI thread. | 95 const GetFileInfoSuccessCallback& success_callback, |
| 96 const ErrorCallback& error_callback); |
| 97 virtual void ReadDirectoryInternal( |
| 98 const base::FilePath& root, |
| 99 const ReadDirectorySuccessCallback& success_callback, |
| 100 const ErrorCallback& error_callback); |
| 101 virtual void CreateSnapshotFileInternal( |
| 102 const base::FilePath& device_file_path, |
| 103 const base::FilePath& local_path, |
| 104 const CreateSnapshotFileSuccessCallback& success_callback, |
| 105 const ErrorCallback& error_callback); |
| 106 virtual void ReadBytesInternal( |
| 107 const base::FilePath& device_file_path, |
| 108 net::IOBuffer* buf, int64 offset, int buf_len, |
| 109 const ReadBytesSuccessCallback& success_callback, |
| 110 const ErrorCallback& error_callback); |
| 111 |
| 112 // Ensures the device is initialized for communication. |
| 113 // If the device is already initialized, call RunTask(). |
85 // | 114 // |
86 // If the device is uninitialized, store the |task_info| in a pending task | 115 // If the device is uninitialized, store the |task_info| in a pending task |
87 // list and runs all the pending tasks once the device is successfully | 116 // queue and runs the pending tasks in the queue once the device is |
88 // initialized. | 117 // successfully initialized. |
89 void EnsureInitAndRunTask(const PendingTaskInfo& task_info); | 118 void EnsureInitAndRunTask(const PendingTaskInfo& task_info); |
90 | 119 |
| 120 // Runs a task. If |task_info.path| is empty, or if the path is cached, runs |
| 121 // the task immediately. |
| 122 // Otherwise, fills the cache first before running the task. |
| 123 // |task_info.task| runs on the UI thread. |
| 124 void RunTask(const PendingTaskInfo& task_info); |
| 125 |
91 // Writes data from the device to the snapshot file path based on the | 126 // Writes data from the device to the snapshot file path based on the |
92 // parameters in |current_snapshot_request_info_| by doing a call-and-reply to | 127 // parameters in |current_snapshot_request_info_| by doing a call-and-reply to |
93 // the UI thread. | 128 // the UI thread. |
94 // | 129 // |
95 // |snapshot_file_info| specifies the metadata details of the snapshot file. | 130 // |snapshot_file_info| specifies the metadata details of the snapshot file. |
96 void WriteDataIntoSnapshotFile(const base::File::Info& snapshot_file_info); | 131 void WriteDataIntoSnapshotFile(const base::File::Info& snapshot_file_info); |
97 | 132 |
98 // Marks the current request as complete and call ProcessNextPendingRequest(). | 133 // Marks the current request as complete and call ProcessNextPendingRequest(). |
99 void PendingRequestDone(); | 134 void PendingRequestDone(); |
100 | 135 |
101 // Processes the next pending request. | 136 // Processes the next pending request. |
102 void ProcessNextPendingRequest(); | 137 void ProcessNextPendingRequest(); |
103 | 138 |
104 // Handles the device initialization event. |succeeded| indicates whether | 139 // Handles the device initialization event. |succeeded| indicates whether |
105 // device initialization succeeded. | 140 // device initialization succeeded. |
106 // | 141 // |
107 // If the device is successfully initialized, runs the next pending task. | 142 // If the device is successfully initialized, runs the next pending task. |
108 void OnInitCompleted(bool succeeded); | 143 void OnInitCompleted(bool succeeded); |
109 | 144 |
110 // Called when GetFileInfo() succeeds. |file_info| specifies the | 145 // Called when GetFileInfo() succeeds. |file_info| specifies the |
111 // requested file details. |success_callback| is invoked to notify the caller | 146 // requested file details. |success_callback| is invoked to notify the caller |
112 // about the requested file details. | 147 // about the requested file details. |
113 void OnDidGetFileInfo(const GetFileInfoSuccessCallback& success_callback, | 148 void OnDidGetFileInfo(const GetFileInfoSuccessCallback& success_callback, |
114 const base::File::Info& file_info); | 149 const base::File::Info& file_info); |
115 | 150 |
116 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to | 151 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to |
117 // get the |root| directory metadata details. |file_info| specifies the |root| | 152 // get the |dir_id| directory metadata details. |file_info| specifies the |
118 // directory details. | 153 // |dir_id| directory details. |
119 // | 154 // |
120 // If |root| is a directory, post a task on the UI thread to read the |root| | 155 // If |dir_id| is a directory, post a task on the UI thread to read the |
121 // directory file entries. | 156 // |dir_id| directory file entries. |
122 // | 157 // |
123 // If |root| is not a directory, |error_callback| is invoked to notify the | 158 // If |dir_id| is not a directory, |error_callback| is invoked to notify the |
124 // caller about the file error and process the next pending request. | 159 // caller about the file error and process the next pending request. |
125 void OnDidGetFileInfoToReadDirectory( | 160 void OnDidGetFileInfoToReadDirectory( |
126 const std::string& root, | 161 uint32 dir_id, |
127 const ReadDirectorySuccessCallback& success_callback, | 162 const ReadDirectorySuccessCallback& success_callback, |
128 const ErrorCallback& error_callback, | 163 const ErrorCallback& error_callback, |
129 const base::File::Info& file_info); | 164 const base::File::Info& file_info); |
130 | 165 |
131 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to | 166 // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to |
132 // create the snapshot file of |snapshot_request_info.device_file_path|. | 167 // create the snapshot file of |snapshot_request_info.device_file_path|. |
133 // |file_info| specifies the device file metadata details. | 168 // |file_info| specifies the device file metadata details. |
134 // | 169 // |
135 // Posts a task on the UI thread to copy the data contents of the device file | 170 // Posts a task on the UI thread to copy the data contents of the device file |
136 // to the snapshot file. | 171 // to the snapshot file. |
137 void OnDidGetFileInfoToCreateSnapshotFile( | 172 void OnDidGetFileInfoToCreateSnapshotFile( |
138 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, | 173 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, |
139 const base::File::Info& file_info); | 174 const base::File::Info& file_info); |
140 | 175 |
141 // Called when ReadDirectory() succeeds. | 176 // Called when ReadDirectory() succeeds. |
142 // | 177 // |
143 // |file_list| contains the directory file entries. | 178 // |dir_id| is the directory read. |
| 179 // |file_list| contains the directory file entries with their file ids. |
144 // |success_callback| is invoked to notify the caller about the directory | 180 // |success_callback| is invoked to notify the caller about the directory |
145 // file entries. | 181 // file entries. |
146 void OnDidReadDirectory(const ReadDirectorySuccessCallback& success_callback, | 182 void OnDidReadDirectory(uint32 dir_id, |
| 183 const ReadDirectorySuccessCallback& success_callback, |
147 const fileapi::AsyncFileUtil::EntryList& file_list); | 184 const fileapi::AsyncFileUtil::EntryList& file_list); |
148 | 185 |
149 // Called when WriteDataIntoSnapshotFile() succeeds. | 186 // Called when WriteDataIntoSnapshotFile() succeeds. |
150 // | 187 // |
151 // |snapshot_file_info| specifies the snapshot file metadata details. | 188 // |snapshot_file_info| specifies the snapshot file metadata details. |
152 // | 189 // |
153 // |current_snapshot_request_info_.success_callback| is invoked to notify the | 190 // |current_snapshot_request_info_.success_callback| is invoked to notify the |
154 // caller about |snapshot_file_info|. | 191 // caller about |snapshot_file_info|. |
155 void OnDidWriteDataIntoSnapshotFile( | 192 void OnDidWriteDataIntoSnapshotFile( |
156 const base::File::Info& snapshot_file_info, | 193 const base::File::Info& snapshot_file_info, |
157 const base::FilePath& snapshot_file_path); | 194 const base::FilePath& snapshot_file_path); |
158 | 195 |
159 // Called when WriteDataIntoSnapshotFile() fails. | 196 // Called when WriteDataIntoSnapshotFile() fails. |
160 // | 197 // |
161 // |error| specifies the file error code. | 198 // |error| specifies the file error code. |
162 // | 199 // |
163 // |current_snapshot_request_info_.error_callback| is invoked to notify the | 200 // |current_snapshot_request_info_.error_callback| is invoked to notify the |
164 // caller about |error|. | 201 // caller about |error|. |
165 void OnWriteDataIntoSnapshotFileError(base::File::Error error); | 202 void OnWriteDataIntoSnapshotFileError(base::File::Error error); |
166 | 203 |
167 // Called when ReadBytes() succeeds. | 204 // Called when ReadBytes() succeeds. |
168 // | 205 // |
169 // |success_callback| is invoked to notify the caller about the read bytes. | 206 // |success_callback| is invoked to notify the caller about the read bytes. |
170 // |bytes_read| is the number of bytes read. | 207 // |bytes_read| is the number of bytes read. |
171 void OnDidReadBytes(const ReadBytesSuccessCallback& success_callback, | 208 void OnDidReadBytes(const ReadBytesSuccessCallback& success_callback, |
172 const base::File::Info& file_info, int bytes_read); | 209 const base::File::Info& file_info, int bytes_read); |
173 | 210 |
174 // Handles the device file |error|. |error_callback| is invoked to notify the | 211 // Called when FillFileCache() succeeds. |
175 // caller about the file error. | 212 void OnDidFillFileCache(const base::FilePath& path, |
| 213 const fileapi::AsyncFileUtil::EntryList& file_list, |
| 214 bool has_more); |
| 215 |
| 216 // Called when FillFileCache() fails. |
| 217 void OnFillFileCacheFailed(base::File::Error error); |
| 218 |
| 219 // Handles the device file |error| while operating on |file_id|. |
| 220 // |error_callback| is invoked to notify the caller about the file error. |
176 void HandleDeviceFileError(const ErrorCallback& error_callback, | 221 void HandleDeviceFileError(const ErrorCallback& error_callback, |
| 222 uint32 file_id, |
177 base::File::Error error); | 223 base::File::Error error); |
178 | 224 |
| 225 // Given a full path, returns a non-empty sub-path that needs to be read into |
| 226 // the cache if such a uncached path exists. |
| 227 // |cached_path| is the portion of |path| that has had cache lookup attempts. |
| 228 base::FilePath NextUncachedPathComponent( |
| 229 const base::FilePath& path, |
| 230 const base::FilePath& cached_path) const; |
| 231 |
| 232 // Fills the file cache using the results from NextUncachedPathComponent(). |
| 233 void FillFileCache(const base::FilePath& uncached_path); |
| 234 |
| 235 // Given a full path, if it exists in the cache, writes the file's id to |id| |
| 236 // and return true. |
| 237 bool CachedPathToId(const base::FilePath& path, uint32* id) const; |
| 238 |
179 // MTP device initialization state. | 239 // MTP device initialization state. |
180 InitializationState init_state_; | 240 InitializationState init_state_; |
181 | 241 |
182 // Used to make sure only one task is in progress at any time. | 242 // Used to make sure only one task is in progress at any time. |
183 // Otherwise the browser will try to send too many requests at once and | 243 // Otherwise the browser will try to send too many requests at once and |
184 // overload the device. | 244 // overload the device. |
185 bool task_in_progress_; | 245 bool task_in_progress_; |
186 | 246 |
187 // Registered file system device path. This path does not | 247 // Registered file system device path. This path does not |
188 // correspond to a real device path (e.g. "/usb:2,2:81282"). | 248 // correspond to a real device path (e.g. "/usb:2,2:81282"). |
189 const base::FilePath device_path_; | 249 const base::FilePath device_path_; |
190 | 250 |
191 // MTP device storage name (e.g. "usb:2,2:81282"). | 251 // MTP device storage name (e.g. "usb:2,2:81282"). |
192 std::string storage_name_; | 252 std::string storage_name_; |
193 | 253 |
194 // A list of pending tasks that needs to be run when the device is | 254 // A list of pending tasks that needs to be run when the device is |
195 // initialized or when the current task in progress is complete. | 255 // initialized or when the current task in progress is complete. |
196 std::queue<PendingTaskInfo> pending_tasks_; | 256 std::deque<PendingTaskInfo> pending_tasks_; |
197 | 257 |
198 // Used to track the current snapshot file request. A snapshot file is created | 258 // Used to track the current snapshot file request. A snapshot file is created |
199 // incrementally. CreateSnapshotFile request reads the device file and writes | 259 // incrementally. CreateSnapshotFile request reads the device file and writes |
200 // to the snapshot file in chunks. In order to retain the order of the | 260 // to the snapshot file in chunks. In order to retain the order of the |
201 // snapshot file requests, make sure there is only one active snapshot file | 261 // snapshot file requests, make sure there is only one active snapshot file |
202 // request at any time. | 262 // request at any time. |
203 scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_; | 263 scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_; |
204 | 264 |
| 265 // A mapping for quick lookups into the |root_node_| tree structure. Since |
| 266 // |root_node_| contains pointers to this map, it must be declared after this |
| 267 // so destruction happens in the right order. |
| 268 FileIdToMTPFileNodeMap file_id_to_node_map_; |
| 269 |
| 270 // The root node of a tree-structure that caches the directory structure of |
| 271 // the MTP device. |
| 272 scoped_ptr<MTPFileNode> root_node_; |
| 273 |
205 // For callbacks that may run after destruction. | 274 // For callbacks that may run after destruction. |
206 base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_; | 275 base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_; |
207 | 276 |
208 DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux); | 277 DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux); |
209 }; | 278 }; |
210 | 279 |
211 #endif // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H
_ | 280 #endif // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H
_ |
OLD | NEW |