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 #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h" | 5 #include "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
11 #include "base/numerics/safe_conversions.h" | 12 #include "base/numerics/safe_conversions.h" |
13 #include "base/strings/string_number_conversions.h" | |
14 #include "base/strings/string_split.h" | |
12 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
13 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h" | 16 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h" |
14 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic e.h" | 17 #include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_servic e.h" |
15 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" | 18 #include "chrome/browser/media_galleries/linux/snapshot_file_details.h" |
16 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
17 #include "net/base/io_buffer.h" | 20 #include "net/base/io_buffer.h" |
21 #include "third_party/cros_system_api/dbus/service_constants.h" | |
18 | 22 |
19 namespace { | 23 namespace { |
20 | 24 |
21 // File path separator constant. | 25 // File path separator constant. |
22 const char kRootPath[] = "/"; | 26 const char kRootPath[] = "/"; |
23 | 27 |
24 // Returns the device relative file path given |file_path|. | 28 // Returns the device relative file path given |file_path|. |
25 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| | 29 // E.g.: If the |file_path| is "/usb:2,2:12345/DCIM" and |registered_dev_path| |
26 // is "/usb:2,2:12345", this function returns the device relative path which is | 30 // is "/usb:2,2:12345", this function returns the device relative path which is |
27 // "DCIM". | 31 // "DCIM". |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 MTPDeviceTaskHelper* task_helper = | 77 MTPDeviceTaskHelper* task_helper = |
74 GetDeviceTaskHelperForStorage(storage_name); | 78 GetDeviceTaskHelperForStorage(storage_name); |
75 if (!task_helper) { | 79 if (!task_helper) { |
76 task_helper = | 80 task_helper = |
77 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( | 81 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( |
78 storage_name); | 82 storage_name); |
79 } | 83 } |
80 task_helper->OpenStorage(storage_name, reply_callback); | 84 task_helper->OpenStorage(storage_name, reply_callback); |
81 } | 85 } |
82 | 86 |
83 // Enumerates the |root| directory file entries. | 87 // Enumerates the |dir_id| directory file entries. |
84 // | 88 // |
85 // Called on the UI thread to dispatch the request to the | 89 // Called on the UI thread to dispatch the request to the |
86 // MediaTransferProtocolManager. | 90 // MediaTransferProtocolManager. |
87 // | 91 // |
88 // |storage_name| specifies the name of the storage device. | 92 // |storage_name| specifies the name of the storage device. |
89 // |success_callback| is called when the ReadDirectory request succeeds. | 93 // |success_callback| is called when the ReadDirectory request succeeds. |
90 // |error_callback| is called when the ReadDirectory request fails. | 94 // |error_callback| is called when the ReadDirectory request fails. |
91 // |success_callback| and |error_callback| runs on the IO thread. | 95 // |success_callback| and |error_callback| runs on the IO thread. |
92 void ReadDirectoryOnUIThread( | 96 void ReadDirectoryOnUIThread( |
93 const std::string& storage_name, | 97 const std::string& storage_name, |
94 const std::string& root, | 98 uint32 dir_id, |
95 const base::Callback< | 99 const base::Callback< |
96 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback, | 100 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback, |
97 const base::Callback<void(base::File::Error)>& error_callback) { | 101 const base::Callback<void(base::File::Error)>& error_callback) { |
98 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 102 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
99 MTPDeviceTaskHelper* task_helper = | 103 MTPDeviceTaskHelper* task_helper = |
100 GetDeviceTaskHelperForStorage(storage_name); | 104 GetDeviceTaskHelperForStorage(storage_name); |
101 if (!task_helper) | 105 if (!task_helper) |
102 return; | 106 return; |
103 task_helper->ReadDirectoryByPath(root, success_callback, error_callback); | 107 task_helper->ReadDirectoryById(dir_id, success_callback, error_callback); |
104 } | 108 } |
105 | 109 |
106 // Gets the |file_path| details. | 110 // Gets the |file_path| details. |
107 // | 111 // |
108 // Called on the UI thread to dispatch the request to the | 112 // Called on the UI thread to dispatch the request to the |
109 // MediaTransferProtocolManager. | 113 // MediaTransferProtocolManager. |
110 // | 114 // |
111 // |storage_name| specifies the name of the storage device. | 115 // |storage_name| specifies the name of the storage device. |
112 // |success_callback| is called when the GetFileInfo request succeeds. | 116 // |success_callback| is called when the GetFileInfo request succeeds. |
113 // |error_callback| is called when the GetFileInfo request fails. | 117 // |error_callback| is called when the GetFileInfo request fails. |
114 // |success_callback| and |error_callback| runs on the IO thread. | 118 // |success_callback| and |error_callback| runs on the IO thread. |
115 void GetFileInfoOnUIThread( | 119 void GetFileInfoOnUIThread( |
116 const std::string& storage_name, | 120 const std::string& storage_name, |
117 const std::string& file_path, | 121 uint32 file_id, |
118 const base::Callback<void(const base::File::Info&)>& success_callback, | 122 const base::Callback<void(const base::File::Info&)>& success_callback, |
119 const base::Callback<void(base::File::Error)>& error_callback) { | 123 const base::Callback<void(base::File::Error)>& error_callback) { |
120 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 124 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
121 MTPDeviceTaskHelper* task_helper = | 125 MTPDeviceTaskHelper* task_helper = |
122 GetDeviceTaskHelperForStorage(storage_name); | 126 GetDeviceTaskHelperForStorage(storage_name); |
123 if (!task_helper) | 127 if (!task_helper) |
124 return; | 128 return; |
125 task_helper->GetFileInfoByPath(file_path, success_callback, error_callback); | 129 task_helper->GetFileInfoById(file_id, success_callback, error_callback); |
126 } | 130 } |
127 | 131 |
128 // Copies the contents of |device_file_path| to |snapshot_file_path|. | 132 // Copies the contents of |device_file_path| to |snapshot_file_path|. |
129 // | 133 // |
130 // Called on the UI thread to dispatch the request to the | 134 // Called on the UI thread to dispatch the request to the |
131 // MediaTransferProtocolManager. | 135 // MediaTransferProtocolManager. |
132 // | 136 // |
133 // |storage_name| specifies the name of the storage device. | 137 // |storage_name| specifies the name of the storage device. |
134 // |device_file_path| specifies the media device file path. | 138 // |device_file_path| specifies the media device file path. |
135 // |snapshot_file_path| specifies the platform path of the snapshot file. | 139 // |snapshot_file_path| specifies the platform path of the snapshot file. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
179 MTPDeviceTaskHelper* task_helper = | 183 MTPDeviceTaskHelper* task_helper = |
180 GetDeviceTaskHelperForStorage(storage_name); | 184 GetDeviceTaskHelperForStorage(storage_name); |
181 if (!task_helper) | 185 if (!task_helper) |
182 return; | 186 return; |
183 task_helper->CloseStorage(); | 187 task_helper->CloseStorage(); |
184 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( | 188 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( |
185 storage_name); | 189 storage_name); |
186 } | 190 } |
187 | 191 |
192 void ReadDirectoryCallbackAdapter( | |
193 const base::Closure& closure, | |
194 const fileapi::AsyncFileUtil::EntryList& /* file_list */, | |
195 bool /* has_more */) { | |
196 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
197 closure.Run(); | |
198 } | |
199 | |
188 } // namespace | 200 } // namespace |
189 | 201 |
190 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo( | 202 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo( |
191 const tracked_objects::Location& location, | 203 const tracked_objects::Location& location, |
192 const base::Closure& task) | 204 const base::Closure& task) |
193 : location(location), | 205 : location(location), |
194 task(task) { | 206 task(task) { |
195 } | 207 } |
196 | 208 |
197 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { | 209 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { |
198 } | 210 } |
199 | 211 |
212 MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode( | |
213 uint32 file_id, | |
214 MTPFileNode* parent, | |
215 FileIdToMTPFileNodeMap* file_id_to_node_map) | |
216 : file_id_(file_id), | |
217 parent_(parent), | |
218 file_id_to_node_map_(file_id_to_node_map) { | |
219 DCHECK(file_id_to_node_map_); | |
220 DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_)); | |
221 (*file_id_to_node_map_)[file_id_] = this; | |
222 } | |
223 | |
224 MTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() { | |
225 size_t erased = file_id_to_node_map_->erase(file_id_); | |
226 DCHECK_EQ(1U, erased); | |
227 } | |
228 | |
229 const MTPDeviceDelegateImplLinux::MTPFileNode* | |
230 MTPDeviceDelegateImplLinux::MTPFileNode::GetChild( | |
231 const std::string& name) const { | |
232 return children_.get(name); | |
233 } | |
234 | |
235 void MTPDeviceDelegateImplLinux::MTPFileNode::AddChild(const std::string& name, | |
236 uint32 id) { | |
237 const MTPFileNode* child = GetChild(name); | |
238 if (child && child->file_id() == id) | |
239 return; | |
240 | |
241 children_.set( | |
242 name, | |
243 make_scoped_ptr(new MTPFileNode(id, this, file_id_to_node_map_))); | |
244 } | |
245 | |
246 void MTPDeviceDelegateImplLinux::MTPFileNode::ClearChildren( | |
247 const std::set<std::string>& children_to_keep) { | |
248 std::set<std::string> children_to_erase; | |
249 for (ChildNodes::const_iterator it = children_.begin(); | |
250 it != children_.end(); ++it) { | |
251 if (ContainsKey(children_to_keep, it->first)) | |
252 continue; | |
253 children_to_erase.insert(it->first); | |
254 } | |
255 for (std::set<std::string>::iterator it = children_to_erase.begin(); | |
256 it != children_to_erase.end(); ++it) { | |
257 children_.take_and_erase(*it); | |
258 } | |
259 } | |
260 | |
261 bool MTPDeviceDelegateImplLinux::MTPFileNode::DeleteChild(uint32 file_id) { | |
262 for (ChildNodes::iterator it = children_.begin(); | |
263 it != children_.end(); ++it) { | |
264 if (it->second->file_id() == file_id) { | |
265 children_.erase(it); | |
266 return true; | |
267 } | |
268 } | |
269 return false; | |
270 } | |
271 | |
200 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( | 272 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( |
201 const std::string& device_location) | 273 const std::string& device_location) |
202 : init_state_(UNINITIALIZED), | 274 : init_state_(UNINITIALIZED), |
203 task_in_progress_(false), | 275 task_in_progress_(false), |
204 device_path_(device_location), | 276 device_path_(device_location), |
277 root_node_(mtpd::kRootFileId, NULL, &file_id_to_node_map_), | |
205 weak_ptr_factory_(this) { | 278 weak_ptr_factory_(this) { |
206 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 279 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
207 DCHECK(!device_path_.empty()); | 280 DCHECK(!device_path_.empty()); |
208 base::RemoveChars(device_location, kRootPath, &storage_name_); | 281 base::RemoveChars(device_location, kRootPath, &storage_name_); |
209 DCHECK(!storage_name_.empty()); | 282 DCHECK(!storage_name_.empty()); |
210 } | 283 } |
211 | 284 |
212 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { | 285 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { |
213 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 286 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
214 } | 287 } |
215 | 288 |
216 void MTPDeviceDelegateImplLinux::GetFileInfo( | 289 void MTPDeviceDelegateImplLinux::GetFileInfo( |
217 const base::FilePath& file_path, | 290 const base::FilePath& file_path, |
218 const GetFileInfoSuccessCallback& success_callback, | 291 const GetFileInfoSuccessCallback& success_callback, |
219 const ErrorCallback& error_callback) { | 292 const ErrorCallback& error_callback) { |
220 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 293 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
221 DCHECK(!file_path.empty()); | 294 DCHECK(!file_path.empty()); |
295 | |
296 uint32 cached_file_id; | |
tommycli
2014/07/09 21:48:31
This block could be abstracted into the EnsureCach
Lei Zhang
2014/07/14 23:46:33
|readdir_success_callback| is different for each o
| |
297 base::FilePath uncached_path = | |
298 NextUncachedPathComponent(file_path, &cached_file_id); | |
299 if (!uncached_path.empty()) { | |
300 base::Closure readdir_success_callback = | |
301 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfo, | |
302 weak_ptr_factory_.GetWeakPtr(), | |
303 file_path, | |
304 success_callback, | |
305 error_callback); | |
306 FillFileCache(uncached_path, cached_file_id, readdir_success_callback, | |
307 error_callback); | |
308 return; | |
309 } | |
310 | |
311 uint32 file_id; | |
312 if (!CachedPathToId(file_path, &file_id)) { | |
313 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); | |
314 return; | |
315 } | |
222 base::Closure call_closure = | 316 base::Closure call_closure = |
223 base::Bind(&GetFileInfoOnUIThread, | 317 base::Bind(&GetFileInfoOnUIThread, |
224 storage_name_, | 318 storage_name_, |
225 GetDeviceRelativePath(device_path_, file_path), | 319 file_id, |
226 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo, | 320 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo, |
227 weak_ptr_factory_.GetWeakPtr(), | 321 weak_ptr_factory_.GetWeakPtr(), |
228 success_callback), | 322 success_callback), |
229 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 323 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
230 weak_ptr_factory_.GetWeakPtr(), | 324 weak_ptr_factory_.GetWeakPtr(), |
231 error_callback)); | 325 error_callback, |
326 file_id)); | |
232 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | 327 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); |
233 } | 328 } |
234 | 329 |
235 void MTPDeviceDelegateImplLinux::ReadDirectory( | 330 void MTPDeviceDelegateImplLinux::ReadDirectory( |
236 const base::FilePath& root, | 331 const base::FilePath& root, |
237 const ReadDirectorySuccessCallback& success_callback, | 332 const ReadDirectorySuccessCallback& success_callback, |
238 const ErrorCallback& error_callback) { | 333 const ErrorCallback& error_callback) { |
239 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 334 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
240 DCHECK(!root.empty()); | 335 DCHECK(!root.empty()); |
241 std::string device_file_relative_path = GetDeviceRelativePath(device_path_, | 336 |
242 root); | 337 uint32 cached_file_id; |
338 base::FilePath uncached_path = | |
339 NextUncachedPathComponent(root, &cached_file_id); | |
340 if (!uncached_path.empty()) { | |
341 base::Closure readdir_success_callback = | |
342 base::Bind(&MTPDeviceDelegateImplLinux::ReadDirectory, | |
343 weak_ptr_factory_.GetWeakPtr(), | |
344 root, | |
345 success_callback, | |
346 error_callback); | |
347 FillFileCache(uncached_path, cached_file_id, readdir_success_callback, | |
348 error_callback); | |
349 return; | |
350 } | |
351 | |
352 uint32 dir_id; | |
353 if (!CachedPathToId(root, &dir_id)) { | |
354 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); | |
355 return; | |
356 } | |
357 | |
243 base::Closure call_closure = | 358 base::Closure call_closure = |
244 base::Bind( | 359 base::Bind( |
245 &GetFileInfoOnUIThread, | 360 &GetFileInfoOnUIThread, |
246 storage_name_, | 361 storage_name_, |
247 device_file_relative_path, | 362 dir_id, |
248 base::Bind( | 363 base::Bind( |
249 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory, | 364 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory, |
250 weak_ptr_factory_.GetWeakPtr(), | 365 weak_ptr_factory_.GetWeakPtr(), |
251 device_file_relative_path, | 366 dir_id, |
252 success_callback, | 367 success_callback, |
253 error_callback), | 368 error_callback), |
254 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 369 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
255 weak_ptr_factory_.GetWeakPtr(), | 370 weak_ptr_factory_.GetWeakPtr(), |
256 error_callback)); | 371 error_callback, |
372 dir_id)); | |
257 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | 373 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); |
258 } | 374 } |
259 | 375 |
260 void MTPDeviceDelegateImplLinux::CreateSnapshotFile( | 376 void MTPDeviceDelegateImplLinux::CreateSnapshotFile( |
261 const base::FilePath& device_file_path, | 377 const base::FilePath& device_file_path, |
262 const base::FilePath& snapshot_file_path, | 378 const base::FilePath& snapshot_file_path, |
263 const CreateSnapshotFileSuccessCallback& success_callback, | 379 const CreateSnapshotFileSuccessCallback& success_callback, |
264 const ErrorCallback& error_callback) { | 380 const ErrorCallback& error_callback) { |
265 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 381 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
266 DCHECK(!device_file_path.empty()); | 382 DCHECK(!device_file_path.empty()); |
267 DCHECK(!snapshot_file_path.empty()); | 383 DCHECK(!snapshot_file_path.empty()); |
268 std::string device_file_relative_path = | 384 |
269 GetDeviceRelativePath(device_path_, device_file_path); | 385 uint32 cached_file_id; |
386 base::FilePath uncached_path = | |
387 NextUncachedPathComponent(device_file_path, &cached_file_id); | |
388 if (!uncached_path.empty()) { | |
389 base::Closure readdir_success_callback = | |
390 base::Bind(&MTPDeviceDelegateImplLinux::CreateSnapshotFile, | |
391 weak_ptr_factory_.GetWeakPtr(), | |
392 device_file_path, | |
393 snapshot_file_path, | |
394 success_callback, | |
395 error_callback); | |
396 FillFileCache(uncached_path, cached_file_id, readdir_success_callback, | |
397 error_callback); | |
398 return; | |
399 } | |
400 | |
401 uint32 file_id; | |
402 if (!CachedPathToId(device_file_path, &file_id)) { | |
403 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); | |
404 return; | |
405 } | |
270 scoped_ptr<SnapshotRequestInfo> request_info( | 406 scoped_ptr<SnapshotRequestInfo> request_info( |
271 new SnapshotRequestInfo(device_file_relative_path, | 407 new SnapshotRequestInfo(file_id, |
272 snapshot_file_path, | 408 snapshot_file_path, |
273 success_callback, | 409 success_callback, |
274 error_callback)); | 410 error_callback)); |
275 base::Closure call_closure = | 411 base::Closure call_closure = |
276 base::Bind( | 412 base::Bind( |
277 &GetFileInfoOnUIThread, | 413 &GetFileInfoOnUIThread, |
278 storage_name_, | 414 storage_name_, |
279 device_file_relative_path, | 415 file_id, |
280 base::Bind( | 416 base::Bind( |
281 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile, | 417 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile, |
282 weak_ptr_factory_.GetWeakPtr(), | 418 weak_ptr_factory_.GetWeakPtr(), |
283 base::Passed(&request_info)), | 419 base::Passed(&request_info)), |
284 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 420 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
285 weak_ptr_factory_.GetWeakPtr(), | 421 weak_ptr_factory_.GetWeakPtr(), |
286 error_callback)); | 422 error_callback, |
423 file_id)); | |
287 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | 424 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); |
288 } | 425 } |
289 | 426 |
290 bool MTPDeviceDelegateImplLinux::IsStreaming() { | 427 bool MTPDeviceDelegateImplLinux::IsStreaming() { |
291 return true; | 428 return true; |
292 } | 429 } |
293 | 430 |
294 void MTPDeviceDelegateImplLinux::ReadBytes( | 431 void MTPDeviceDelegateImplLinux::ReadBytes( |
295 const base::FilePath& device_file_path, | 432 const base::FilePath& device_file_path, |
296 net::IOBuffer* buf, int64 offset, int buf_len, | 433 net::IOBuffer* buf, int64 offset, int buf_len, |
297 const ReadBytesSuccessCallback& success_callback, | 434 const ReadBytesSuccessCallback& success_callback, |
298 const ErrorCallback& error_callback) { | 435 const ErrorCallback& error_callback) { |
299 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 436 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
300 DCHECK(!device_file_path.empty()); | 437 DCHECK(!device_file_path.empty()); |
301 std::string device_file_relative_path = | 438 |
302 GetDeviceRelativePath(device_path_, device_file_path); | 439 uint32 cached_file_id; |
440 base::FilePath uncached_path = | |
441 NextUncachedPathComponent(device_file_path, &cached_file_id); | |
442 if (!uncached_path.empty()) { | |
443 base::Closure readdir_success_callback = | |
444 base::Bind(&MTPDeviceDelegateImplLinux::ReadBytes, | |
445 weak_ptr_factory_.GetWeakPtr(), | |
446 device_file_path, | |
447 make_scoped_refptr(buf), | |
448 offset, | |
449 buf_len, | |
450 success_callback, | |
451 error_callback); | |
452 FillFileCache(uncached_path, cached_file_id, readdir_success_callback, | |
453 error_callback); | |
454 return; | |
455 } | |
456 | |
457 uint32 file_id; | |
458 if (!CachedPathToId(device_file_path, &file_id)) { | |
459 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND); | |
460 return; | |
461 } | |
303 | 462 |
304 ReadBytesRequest request( | 463 ReadBytesRequest request( |
305 device_file_relative_path, buf, offset, buf_len, | 464 file_id, buf, offset, buf_len, |
306 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes, | 465 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes, |
307 weak_ptr_factory_.GetWeakPtr(), success_callback), | 466 weak_ptr_factory_.GetWeakPtr(), |
467 success_callback), | |
308 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 468 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
309 weak_ptr_factory_.GetWeakPtr(), error_callback)); | 469 weak_ptr_factory_.GetWeakPtr(), |
470 error_callback, | |
471 file_id)); | |
310 | 472 |
311 base::Closure call_closure = | 473 base::Closure call_closure = |
312 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); | 474 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); |
313 | 475 |
314 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); | 476 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure)); |
315 } | 477 } |
316 | 478 |
317 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { | 479 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { |
318 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 480 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
319 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. | 481 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. |
(...skipping 28 matching lines...) Expand all Loading... | |
348 } | 510 } |
349 } | 511 } |
350 | 512 |
351 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( | 513 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( |
352 const base::File::Info& file_info) { | 514 const base::File::Info& file_info) { |
353 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 515 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
354 DCHECK(current_snapshot_request_info_.get()); | 516 DCHECK(current_snapshot_request_info_.get()); |
355 DCHECK_GT(file_info.size, 0); | 517 DCHECK_GT(file_info.size, 0); |
356 task_in_progress_ = true; | 518 task_in_progress_ = true; |
357 SnapshotRequestInfo request_info( | 519 SnapshotRequestInfo request_info( |
358 current_snapshot_request_info_->device_file_path, | 520 current_snapshot_request_info_->file_id, |
359 current_snapshot_request_info_->snapshot_file_path, | 521 current_snapshot_request_info_->snapshot_file_path, |
360 base::Bind( | 522 base::Bind( |
361 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile, | 523 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile, |
362 weak_ptr_factory_.GetWeakPtr()), | 524 weak_ptr_factory_.GetWeakPtr()), |
363 base::Bind( | 525 base::Bind( |
364 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError, | 526 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError, |
365 weak_ptr_factory_.GetWeakPtr())); | 527 weak_ptr_factory_.GetWeakPtr())); |
366 | 528 |
367 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, | 529 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, |
368 storage_name_, | 530 storage_name_, |
(...skipping 28 matching lines...) Expand all Loading... | |
397 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo( | 559 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo( |
398 const GetFileInfoSuccessCallback& success_callback, | 560 const GetFileInfoSuccessCallback& success_callback, |
399 const base::File::Info& file_info) { | 561 const base::File::Info& file_info) { |
400 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 562 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
401 success_callback.Run(file_info); | 563 success_callback.Run(file_info); |
402 task_in_progress_ = false; | 564 task_in_progress_ = false; |
403 ProcessNextPendingRequest(); | 565 ProcessNextPendingRequest(); |
404 } | 566 } |
405 | 567 |
406 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( | 568 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( |
407 const std::string& root, | 569 uint32 dir_id, |
408 const ReadDirectorySuccessCallback& success_callback, | 570 const ReadDirectorySuccessCallback& success_callback, |
409 const ErrorCallback& error_callback, | 571 const ErrorCallback& error_callback, |
410 const base::File::Info& file_info) { | 572 const base::File::Info& file_info) { |
411 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 573 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
412 DCHECK(task_in_progress_); | 574 DCHECK(task_in_progress_); |
413 if (!file_info.is_directory) { | 575 if (!file_info.is_directory) { |
414 return HandleDeviceFileError(error_callback, | 576 return HandleDeviceFileError(error_callback, |
577 dir_id, | |
415 base::File::FILE_ERROR_NOT_A_DIRECTORY); | 578 base::File::FILE_ERROR_NOT_A_DIRECTORY); |
416 } | 579 } |
417 | 580 |
418 base::Closure task_closure = | 581 base::Closure task_closure = |
419 base::Bind(&ReadDirectoryOnUIThread, | 582 base::Bind(&ReadDirectoryOnUIThread, |
420 storage_name_, | 583 storage_name_, |
421 root, | 584 dir_id, |
422 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, | 585 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, |
423 weak_ptr_factory_.GetWeakPtr(), | 586 weak_ptr_factory_.GetWeakPtr(), |
587 dir_id, | |
424 success_callback), | 588 success_callback), |
425 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | 589 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, |
426 weak_ptr_factory_.GetWeakPtr(), | 590 weak_ptr_factory_.GetWeakPtr(), |
427 error_callback)); | 591 error_callback, |
592 dir_id)); | |
428 content::BrowserThread::PostTask(content::BrowserThread::UI, | 593 content::BrowserThread::PostTask(content::BrowserThread::UI, |
429 FROM_HERE, | 594 FROM_HERE, |
430 task_closure); | 595 task_closure); |
431 } | 596 } |
432 | 597 |
433 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile( | 598 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile( |
434 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, | 599 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, |
435 const base::File::Info& file_info) { | 600 const base::File::Info& file_info) { |
436 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 601 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
437 DCHECK(!current_snapshot_request_info_.get()); | 602 DCHECK(!current_snapshot_request_info_.get()); |
438 DCHECK(snapshot_request_info.get()); | 603 DCHECK(snapshot_request_info.get()); |
439 DCHECK(task_in_progress_); | 604 DCHECK(task_in_progress_); |
440 base::File::Error error = base::File::FILE_OK; | 605 base::File::Error error = base::File::FILE_OK; |
441 if (file_info.is_directory) | 606 if (file_info.is_directory) |
442 error = base::File::FILE_ERROR_NOT_A_FILE; | 607 error = base::File::FILE_ERROR_NOT_A_FILE; |
443 else if (file_info.size < 0 || file_info.size > kuint32max) | 608 else if (file_info.size < 0 || file_info.size > kuint32max) |
444 error = base::File::FILE_ERROR_FAILED; | 609 error = base::File::FILE_ERROR_FAILED; |
445 | 610 |
446 if (error != base::File::FILE_OK) | 611 if (error != base::File::FILE_OK) |
447 return HandleDeviceFileError(snapshot_request_info->error_callback, error); | 612 return HandleDeviceFileError(snapshot_request_info->error_callback, |
613 snapshot_request_info->file_id, | |
614 error); | |
448 | 615 |
449 base::File::Info snapshot_file_info(file_info); | 616 base::File::Info snapshot_file_info(file_info); |
450 // Modify the last modified time to null. This prevents the time stamp | 617 // Modify the last modified time to null. This prevents the time stamp |
451 // verfication in LocalFileStreamReader. | 618 // verfication in LocalFileStreamReader. |
452 snapshot_file_info.last_modified = base::Time(); | 619 snapshot_file_info.last_modified = base::Time(); |
453 | 620 |
454 current_snapshot_request_info_.reset(snapshot_request_info.release()); | 621 current_snapshot_request_info_.reset(snapshot_request_info.release()); |
455 if (file_info.size == 0) { | 622 if (file_info.size == 0) { |
456 // Empty snapshot file. | 623 // Empty snapshot file. |
457 return OnDidWriteDataIntoSnapshotFile( | 624 return OnDidWriteDataIntoSnapshotFile( |
458 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path); | 625 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path); |
459 } | 626 } |
460 WriteDataIntoSnapshotFile(snapshot_file_info); | 627 WriteDataIntoSnapshotFile(snapshot_file_info); |
461 } | 628 } |
462 | 629 |
463 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( | 630 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( |
631 uint32 dir_id, | |
464 const ReadDirectorySuccessCallback& success_callback, | 632 const ReadDirectorySuccessCallback& success_callback, |
465 const fileapi::AsyncFileUtil::EntryList& file_list) { | 633 const fileapi::AsyncFileUtil::EntryList& file_list) { |
466 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 634 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
467 success_callback.Run(file_list, false /*no more entries*/); | 635 |
636 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id); | |
637 DCHECK(it != file_id_to_node_map_.end()); | |
638 MTPFileNode* dir_node = it->second; | |
639 std::set<std::string> children_to_keep; | |
640 | |
641 fileapi::AsyncFileUtil::EntryList normalized_file_list; | |
tommycli
2014/07/09 21:48:31
My initial reaction was: Why not just clear the li
Lei Zhang
2014/07/14 23:46:33
Done.
| |
642 for (size_t i = 0; i < file_list.size(); ++i) { | |
643 normalized_file_list.push_back(file_list[i]); | |
644 fileapi::DirectoryEntry& entry = normalized_file_list.back(); | |
645 | |
646 // |entry.name| has the file id encoded in it. Decode here. | |
647 size_t separator_idx = entry.name.find_last_of(','); | |
648 DCHECK_NE(std::string::npos, separator_idx); | |
649 std::string file_id_str = entry.name.substr(separator_idx); | |
650 file_id_str = file_id_str.substr(1); // Get rid of the comma. | |
651 uint32 file_id = 0; | |
652 bool ret = base::StringToUint(file_id_str, &file_id); | |
653 DCHECK(ret); | |
654 entry.name = entry.name.substr(0, separator_idx); | |
655 | |
656 // Refresh the in memory tree. | |
657 dir_node->AddChild(entry.name, file_id); | |
658 children_to_keep.insert(entry.name); | |
659 } | |
660 dir_node->ClearChildren(children_to_keep); | |
661 | |
662 success_callback.Run(normalized_file_list, false /*no more entries*/); | |
468 task_in_progress_ = false; | 663 task_in_progress_ = false; |
469 ProcessNextPendingRequest(); | 664 ProcessNextPendingRequest(); |
470 } | 665 } |
471 | 666 |
472 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( | 667 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( |
473 const base::File::Info& file_info, | 668 const base::File::Info& file_info, |
474 const base::FilePath& snapshot_file_path) { | 669 const base::FilePath& snapshot_file_path) { |
475 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 670 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
476 DCHECK(current_snapshot_request_info_.get()); | 671 DCHECK(current_snapshot_request_info_.get()); |
477 DCHECK(task_in_progress_); | 672 DCHECK(task_in_progress_); |
(...skipping 20 matching lines...) Expand all Loading... | |
498 const base::File::Info& file_info, int bytes_read) { | 693 const base::File::Info& file_info, int bytes_read) { |
499 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 694 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
500 DCHECK(task_in_progress_); | 695 DCHECK(task_in_progress_); |
501 success_callback.Run(file_info, bytes_read); | 696 success_callback.Run(file_info, bytes_read); |
502 task_in_progress_ = false; | 697 task_in_progress_ = false; |
503 ProcessNextPendingRequest(); | 698 ProcessNextPendingRequest(); |
504 } | 699 } |
505 | 700 |
506 void MTPDeviceDelegateImplLinux::HandleDeviceFileError( | 701 void MTPDeviceDelegateImplLinux::HandleDeviceFileError( |
507 const ErrorCallback& error_callback, | 702 const ErrorCallback& error_callback, |
703 uint32 file_id, | |
508 base::File::Error error) { | 704 base::File::Error error) { |
509 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 705 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
510 DCHECK(task_in_progress_); | 706 |
707 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(file_id); | |
708 if (it != file_id_to_node_map_.end()) { | |
709 MTPFileNode* parent = it->second->parent(); | |
710 if (parent) { | |
711 bool ret = parent->DeleteChild(file_id); | |
712 DCHECK(ret); | |
713 } | |
714 } | |
511 error_callback.Run(error); | 715 error_callback.Run(error); |
512 task_in_progress_ = false; | 716 task_in_progress_ = false; |
513 ProcessNextPendingRequest(); | 717 ProcessNextPendingRequest(); |
514 } | 718 } |
515 | 719 |
720 base::FilePath MTPDeviceDelegateImplLinux::NextUncachedPathComponent( | |
tommycli
2014/07/09 21:48:31
I really like how this method is structured.
| |
721 const base::FilePath& path, | |
722 uint32* cached_file_id) const { | |
723 DCHECK(cached_file_id); | |
724 | |
725 base::FilePath uncached_path; | |
726 std::string device_relpath = GetDeviceRelativePath(device_path_, path); | |
727 if (!device_relpath.empty() && device_relpath != kRootPath) { | |
728 uncached_path = device_path_; | |
729 std::vector<std::string> device_relpath_components; | |
730 base::SplitString(device_relpath, '/', &device_relpath_components); | |
731 DCHECK(!device_relpath_components.empty()); | |
732 bool all_components_cached = true; | |
733 uint32 file_id; | |
734 const MTPFileNode* current_node = &root_node_; | |
735 for (size_t i = 0; i < device_relpath_components.size(); ++i) { | |
736 file_id = current_node->file_id(); | |
737 | |
738 current_node = current_node->GetChild(device_relpath_components[i]); | |
739 if (!current_node) { | |
740 all_components_cached = false; | |
741 break; | |
742 } | |
743 uncached_path = uncached_path.Append(device_relpath_components[i]); | |
744 } | |
745 if (all_components_cached) | |
746 uncached_path.clear(); | |
747 else | |
748 *cached_file_id = file_id; | |
749 } | |
750 return uncached_path; | |
751 } | |
752 | |
753 void MTPDeviceDelegateImplLinux::FillFileCache( | |
754 const base::FilePath& uncached_path, | |
755 uint32 cached_file_id, | |
756 const base::Closure success_callback, | |
757 const ErrorCallback& error_callback) { | |
758 DCHECK(!uncached_path.empty()); | |
759 | |
760 ReadDirectorySuccessCallback readdir_success_callback = | |
761 base::Bind(&ReadDirectoryCallbackAdapter, success_callback); | |
762 ReadDirectory(uncached_path, | |
763 readdir_success_callback, | |
764 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, | |
765 weak_ptr_factory_.GetWeakPtr(), | |
766 error_callback, | |
767 cached_file_id)); | |
768 } | |
769 | |
770 | |
771 bool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path, | |
772 uint32* id) const { | |
773 DCHECK(id); | |
774 | |
775 std::string device_relpath = GetDeviceRelativePath(device_path_, path); | |
776 if (device_relpath.empty()) | |
777 return false; | |
778 std::vector<std::string> device_relpath_components; | |
779 if (device_relpath != kRootPath) | |
780 base::SplitString(device_relpath, '/', &device_relpath_components); | |
781 const MTPFileNode* current_node = &root_node_; | |
782 for (size_t i = 0; i < device_relpath_components.size(); ++i) { | |
783 current_node = current_node->GetChild(device_relpath_components[i]); | |
784 if (!current_node) | |
785 return false; | |
786 } | |
787 *id = current_node->file_id(); | |
788 return true; | |
789 } | |
790 | |
516 void CreateMTPDeviceAsyncDelegate( | 791 void CreateMTPDeviceAsyncDelegate( |
517 const std::string& device_location, | 792 const std::string& device_location, |
518 const CreateMTPDeviceAsyncDelegateCallback& callback) { | 793 const CreateMTPDeviceAsyncDelegateCallback& callback) { |
519 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 794 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
520 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); | 795 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); |
521 } | 796 } |
OLD | NEW |