Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc

Issue 377383002: Media Galleries: Access MTP devices by file ids rather than file paths. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <set>
9 #include <vector>
8 10
9 #include "base/bind.h" 11 #include "base/bind.h"
10 #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"
17 #include "net/base/io_buffer.h" 19 #include "net/base/io_buffer.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
18 21
19 namespace { 22 namespace {
20 23
21 // File path separator constant. 24 // File path separator constant.
22 const char kRootPath[] = "/"; 25 const char kRootPath[] = "/";
23 26
24 // Returns the device relative file path given |file_path|. 27 // 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| 28 // 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 29 // is "/usb:2,2:12345", this function returns the device relative path which is
27 // "DCIM". 30 // "DCIM".
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 MTPDeviceTaskHelper* task_helper = 76 MTPDeviceTaskHelper* task_helper =
74 GetDeviceTaskHelperForStorage(storage_name); 77 GetDeviceTaskHelperForStorage(storage_name);
75 if (!task_helper) { 78 if (!task_helper) {
76 task_helper = 79 task_helper =
77 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper( 80 MTPDeviceTaskHelperMapService::GetInstance()->CreateDeviceTaskHelper(
78 storage_name); 81 storage_name);
79 } 82 }
80 task_helper->OpenStorage(storage_name, reply_callback); 83 task_helper->OpenStorage(storage_name, reply_callback);
81 } 84 }
82 85
83 // Enumerates the |root| directory file entries. 86 // Enumerates the |dir_id| directory file entries.
84 // 87 //
85 // Called on the UI thread to dispatch the request to the 88 // Called on the UI thread to dispatch the request to the
86 // MediaTransferProtocolManager. 89 // MediaTransferProtocolManager.
87 // 90 //
88 // |storage_name| specifies the name of the storage device. 91 // |storage_name| specifies the name of the storage device.
89 // |success_callback| is called when the ReadDirectory request succeeds. 92 // |success_callback| is called when the ReadDirectory request succeeds.
90 // |error_callback| is called when the ReadDirectory request fails. 93 // |error_callback| is called when the ReadDirectory request fails.
91 // |success_callback| and |error_callback| runs on the IO thread. 94 // |success_callback| and |error_callback| runs on the IO thread.
92 void ReadDirectoryOnUIThread( 95 void ReadDirectoryOnUIThread(
93 const std::string& storage_name, 96 const std::string& storage_name,
94 const std::string& root, 97 uint32 dir_id,
95 const base::Callback< 98 const base::Callback<
96 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback, 99 void(const fileapi::AsyncFileUtil::EntryList&)>& success_callback,
97 const base::Callback<void(base::File::Error)>& error_callback) { 100 const base::Callback<void(base::File::Error)>& error_callback) {
98 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 101 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
99 MTPDeviceTaskHelper* task_helper = 102 MTPDeviceTaskHelper* task_helper =
100 GetDeviceTaskHelperForStorage(storage_name); 103 GetDeviceTaskHelperForStorage(storage_name);
101 if (!task_helper) 104 if (!task_helper)
102 return; 105 return;
103 task_helper->ReadDirectoryByPath(root, success_callback, error_callback); 106 task_helper->ReadDirectoryById(dir_id, success_callback, error_callback);
104 } 107 }
105 108
106 // Gets the |file_path| details. 109 // Gets the |file_path| details.
107 // 110 //
108 // Called on the UI thread to dispatch the request to the 111 // Called on the UI thread to dispatch the request to the
109 // MediaTransferProtocolManager. 112 // MediaTransferProtocolManager.
110 // 113 //
111 // |storage_name| specifies the name of the storage device. 114 // |storage_name| specifies the name of the storage device.
112 // |success_callback| is called when the GetFileInfo request succeeds. 115 // |success_callback| is called when the GetFileInfo request succeeds.
113 // |error_callback| is called when the GetFileInfo request fails. 116 // |error_callback| is called when the GetFileInfo request fails.
114 // |success_callback| and |error_callback| runs on the IO thread. 117 // |success_callback| and |error_callback| runs on the IO thread.
115 void GetFileInfoOnUIThread( 118 void GetFileInfoOnUIThread(
116 const std::string& storage_name, 119 const std::string& storage_name,
117 const std::string& file_path, 120 uint32 file_id,
118 const base::Callback<void(const base::File::Info&)>& success_callback, 121 const MTPDeviceAsyncDelegate::GetFileInfoSuccessCallback& success_callback,
119 const base::Callback<void(base::File::Error)>& error_callback) { 122 const MTPDeviceAsyncDelegate::ErrorCallback& error_callback) {
120 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 123 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
121 MTPDeviceTaskHelper* task_helper = 124 MTPDeviceTaskHelper* task_helper =
122 GetDeviceTaskHelperForStorage(storage_name); 125 GetDeviceTaskHelperForStorage(storage_name);
123 if (!task_helper) 126 if (!task_helper)
124 return; 127 return;
125 task_helper->GetFileInfoByPath(file_path, success_callback, error_callback); 128 task_helper->GetFileInfoById(file_id, success_callback, error_callback);
126 } 129 }
127 130
128 // Copies the contents of |device_file_path| to |snapshot_file_path|. 131 // Copies the contents of |device_file_path| to |snapshot_file_path|.
129 // 132 //
130 // Called on the UI thread to dispatch the request to the 133 // Called on the UI thread to dispatch the request to the
131 // MediaTransferProtocolManager. 134 // MediaTransferProtocolManager.
132 // 135 //
133 // |storage_name| specifies the name of the storage device. 136 // |storage_name| specifies the name of the storage device.
134 // |device_file_path| specifies the media device file path. 137 // |device_file_path| specifies the media device file path.
135 // |snapshot_file_path| specifies the platform path of the snapshot file. 138 // |snapshot_file_path| specifies the platform path of the snapshot file.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 if (!task_helper) 184 if (!task_helper)
182 return; 185 return;
183 task_helper->CloseStorage(); 186 task_helper->CloseStorage();
184 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper( 187 MTPDeviceTaskHelperMapService::GetInstance()->DestroyDeviceTaskHelper(
185 storage_name); 188 storage_name);
186 } 189 }
187 190
188 } // namespace 191 } // namespace
189 192
190 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo( 193 MTPDeviceDelegateImplLinux::PendingTaskInfo::PendingTaskInfo(
194 const base::FilePath& path,
195 content::BrowserThread::ID thread_id,
191 const tracked_objects::Location& location, 196 const tracked_objects::Location& location,
192 const base::Closure& task) 197 const base::Closure& task)
193 : location(location), 198 : path(path),
199 thread_id(thread_id),
200 location(location),
194 task(task) { 201 task(task) {
195 } 202 }
196 203
197 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() { 204 MTPDeviceDelegateImplLinux::PendingTaskInfo::~PendingTaskInfo() {
198 } 205 }
199 206
207 // Represents a file on the MTP device.
208 // Lives on the IO thread.
209 class MTPDeviceDelegateImplLinux::MTPFileNode {
210 public:
211 MTPFileNode(uint32 file_id,
212 MTPFileNode* parent,
213 FileIdToMTPFileNodeMap* file_id_to_node_map);
214 ~MTPFileNode();
215
216 const MTPFileNode* GetChild(const std::string& name) const;
217
218 void EnsureChildExists(const std::string& name, uint32 id);
219
220 // Clears all the children, except those in |children_to_keep|.
221 void ClearNonexistentChildren(
222 const std::set<std::string>& children_to_keep);
223
224 bool DeleteChild(uint32 file_id);
225
226 uint32 file_id() const { return file_id_; }
227 MTPFileNode* parent() { return parent_; }
228
229 private:
230 // Container for holding a node's children.
231 typedef base::ScopedPtrHashMap<std::string, MTPFileNode> ChildNodes;
232
233 const uint32 file_id_;
234 ChildNodes children_;
235 MTPFileNode* const parent_;
236 FileIdToMTPFileNodeMap* file_id_to_node_map_;
237
238 DISALLOW_COPY_AND_ASSIGN(MTPFileNode);
239 };
240
241 MTPDeviceDelegateImplLinux::MTPFileNode::MTPFileNode(
242 uint32 file_id,
243 MTPFileNode* parent,
244 FileIdToMTPFileNodeMap* file_id_to_node_map)
245 : file_id_(file_id),
246 parent_(parent),
247 file_id_to_node_map_(file_id_to_node_map) {
248 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
249 DCHECK(file_id_to_node_map_);
250 DCHECK(!ContainsKey(*file_id_to_node_map_, file_id_));
251 (*file_id_to_node_map_)[file_id_] = this;
252 }
253
254 MTPDeviceDelegateImplLinux::MTPFileNode::~MTPFileNode() {
255 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
256 size_t erased = file_id_to_node_map_->erase(file_id_);
257 DCHECK_EQ(1U, erased);
258 }
259
260 const MTPDeviceDelegateImplLinux::MTPFileNode*
261 MTPDeviceDelegateImplLinux::MTPFileNode::GetChild(
262 const std::string& name) const {
263 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
264 return children_.get(name);
265 }
266
267 void MTPDeviceDelegateImplLinux::MTPFileNode::EnsureChildExists(
268 const std::string& name,
269 uint32 id) {
270 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
271 const MTPFileNode* child = GetChild(name);
272 if (child && child->file_id() == id)
273 return;
274
275 children_.set(
276 name,
277 make_scoped_ptr(new MTPFileNode(id, this, file_id_to_node_map_)));
278 }
279
280 void MTPDeviceDelegateImplLinux::MTPFileNode::ClearNonexistentChildren(
281 const std::set<std::string>& children_to_keep) {
282 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
283 std::set<std::string> children_to_erase;
284 for (ChildNodes::const_iterator it = children_.begin();
285 it != children_.end(); ++it) {
286 if (ContainsKey(children_to_keep, it->first))
287 continue;
288 children_to_erase.insert(it->first);
289 }
290 for (std::set<std::string>::iterator it = children_to_erase.begin();
291 it != children_to_erase.end(); ++it) {
292 children_.take_and_erase(*it);
293 }
294 }
295
296 bool MTPDeviceDelegateImplLinux::MTPFileNode::DeleteChild(uint32 file_id) {
297 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
298 for (ChildNodes::iterator it = children_.begin();
299 it != children_.end(); ++it) {
300 if (it->second->file_id() == file_id) {
301 children_.erase(it);
302 return true;
303 }
304 }
305 return false;
306 }
307
200 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux( 308 MTPDeviceDelegateImplLinux::MTPDeviceDelegateImplLinux(
201 const std::string& device_location) 309 const std::string& device_location)
202 : init_state_(UNINITIALIZED), 310 : init_state_(UNINITIALIZED),
203 task_in_progress_(false), 311 task_in_progress_(false),
204 device_path_(device_location), 312 device_path_(device_location),
313 root_node_(new MTPFileNode(mtpd::kRootFileId,
314 NULL,
315 &file_id_to_node_map_)),
205 weak_ptr_factory_(this) { 316 weak_ptr_factory_(this) {
206 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 317 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
207 DCHECK(!device_path_.empty()); 318 DCHECK(!device_path_.empty());
208 base::RemoveChars(device_location, kRootPath, &storage_name_); 319 base::RemoveChars(device_location, kRootPath, &storage_name_);
209 DCHECK(!storage_name_.empty()); 320 DCHECK(!storage_name_.empty());
210 } 321 }
211 322
212 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() { 323 MTPDeviceDelegateImplLinux::~MTPDeviceDelegateImplLinux() {
213 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 324 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
214 } 325 }
215 326
216 void MTPDeviceDelegateImplLinux::GetFileInfo( 327 void MTPDeviceDelegateImplLinux::GetFileInfo(
217 const base::FilePath& file_path, 328 const base::FilePath& file_path,
218 const GetFileInfoSuccessCallback& success_callback, 329 const GetFileInfoSuccessCallback& success_callback,
219 const ErrorCallback& error_callback) { 330 const ErrorCallback& error_callback) {
220 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 331 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
221 DCHECK(!file_path.empty()); 332 DCHECK(!file_path.empty());
222 base::Closure call_closure = 333 base::Closure closure =
223 base::Bind(&GetFileInfoOnUIThread, 334 base::Bind(&MTPDeviceDelegateImplLinux::GetFileInfoInternal,
224 storage_name_, 335 weak_ptr_factory_.GetWeakPtr(),
225 GetDeviceRelativePath(device_path_, file_path), 336 file_path,
226 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo, 337 success_callback,
227 weak_ptr_factory_.GetWeakPtr(), 338 error_callback);
228 success_callback), 339 EnsureInitAndRunTask(PendingTaskInfo(file_path,
229 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, 340 content::BrowserThread::IO,
230 weak_ptr_factory_.GetWeakPtr(), 341 FROM_HERE,
231 error_callback)); 342 closure));
232 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
233 } 343 }
234 344
235 void MTPDeviceDelegateImplLinux::ReadDirectory( 345 void MTPDeviceDelegateImplLinux::ReadDirectory(
236 const base::FilePath& root, 346 const base::FilePath& root,
237 const ReadDirectorySuccessCallback& success_callback, 347 const ReadDirectorySuccessCallback& success_callback,
238 const ErrorCallback& error_callback) { 348 const ErrorCallback& error_callback) {
239 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 349 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
240 DCHECK(!root.empty()); 350 DCHECK(!root.empty());
241 std::string device_file_relative_path = GetDeviceRelativePath(device_path_, 351 base::Closure closure =
242 root); 352 base::Bind(&MTPDeviceDelegateImplLinux::ReadDirectoryInternal,
243 base::Closure call_closure = 353 weak_ptr_factory_.GetWeakPtr(),
244 base::Bind( 354 root,
245 &GetFileInfoOnUIThread, 355 success_callback,
246 storage_name_, 356 error_callback);
247 device_file_relative_path, 357 EnsureInitAndRunTask(PendingTaskInfo(root,
248 base::Bind( 358 content::BrowserThread::IO,
249 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory, 359 FROM_HERE,
250 weak_ptr_factory_.GetWeakPtr(), 360 closure));
251 device_file_relative_path,
252 success_callback,
253 error_callback),
254 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
255 weak_ptr_factory_.GetWeakPtr(),
256 error_callback));
257 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
258 } 361 }
259 362
260 void MTPDeviceDelegateImplLinux::CreateSnapshotFile( 363 void MTPDeviceDelegateImplLinux::CreateSnapshotFile(
261 const base::FilePath& device_file_path, 364 const base::FilePath& device_file_path,
262 const base::FilePath& local_path, 365 const base::FilePath& local_path,
263 const CreateSnapshotFileSuccessCallback& success_callback, 366 const CreateSnapshotFileSuccessCallback& success_callback,
264 const ErrorCallback& error_callback) { 367 const ErrorCallback& error_callback) {
265 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 368 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
266 DCHECK(!device_file_path.empty()); 369 DCHECK(!device_file_path.empty());
267 DCHECK(!local_path.empty()); 370 DCHECK(!local_path.empty());
268 std::string device_file_relative_path = 371 base::Closure closure =
269 GetDeviceRelativePath(device_path_, device_file_path); 372 base::Bind(&MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal,
270 scoped_ptr<SnapshotRequestInfo> request_info( 373 weak_ptr_factory_.GetWeakPtr(),
271 new SnapshotRequestInfo(device_file_relative_path, 374 device_file_path,
272 local_path, 375 local_path,
273 success_callback, 376 success_callback,
274 error_callback)); 377 error_callback);
275 base::Closure call_closure = 378 EnsureInitAndRunTask(PendingTaskInfo(device_file_path,
276 base::Bind( 379 content::BrowserThread::IO,
277 &GetFileInfoOnUIThread, 380 FROM_HERE,
278 storage_name_, 381 closure));
279 device_file_relative_path,
280 base::Bind(
281 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile,
282 weak_ptr_factory_.GetWeakPtr(),
283 base::Passed(&request_info)),
284 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
285 weak_ptr_factory_.GetWeakPtr(),
286 error_callback));
287 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
288 } 382 }
289 383
290 bool MTPDeviceDelegateImplLinux::IsStreaming() { 384 bool MTPDeviceDelegateImplLinux::IsStreaming() {
291 return true; 385 return true;
292 } 386 }
293 387
294 void MTPDeviceDelegateImplLinux::ReadBytes( 388 void MTPDeviceDelegateImplLinux::ReadBytes(
295 const base::FilePath& device_file_path, 389 const base::FilePath& device_file_path,
296 net::IOBuffer* buf, int64 offset, int buf_len, 390 net::IOBuffer* buf, int64 offset, int buf_len,
297 const ReadBytesSuccessCallback& success_callback, 391 const ReadBytesSuccessCallback& success_callback,
298 const ErrorCallback& error_callback) { 392 const ErrorCallback& error_callback) {
299 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 393 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
300 DCHECK(!device_file_path.empty()); 394 DCHECK(!device_file_path.empty());
301 std::string device_file_relative_path = 395 base::Closure closure =
302 GetDeviceRelativePath(device_path_, device_file_path); 396 base::Bind(&MTPDeviceDelegateImplLinux::ReadBytesInternal,
303 397 weak_ptr_factory_.GetWeakPtr(),
304 ReadBytesRequest request( 398 device_file_path,
305 device_file_relative_path, buf, offset, buf_len, 399 make_scoped_refptr(buf),
306 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes, 400 offset,
307 weak_ptr_factory_.GetWeakPtr(), success_callback), 401 buf_len,
308 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, 402 success_callback,
309 weak_ptr_factory_.GetWeakPtr(), error_callback)); 403 error_callback);
310 404 EnsureInitAndRunTask(PendingTaskInfo(device_file_path,
311 base::Closure call_closure = 405 content::BrowserThread::IO,
312 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request)); 406 FROM_HERE,
313 407 closure));
314 EnsureInitAndRunTask(PendingTaskInfo(FROM_HERE, call_closure));
315 } 408 }
316 409
317 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() { 410 void MTPDeviceDelegateImplLinux::CancelPendingTasksAndDeleteDelegate() {
318 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 411 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
319 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object. 412 // To cancel all the pending tasks, destroy the MTPDeviceTaskHelper object.
320 content::BrowserThread::PostTask( 413 content::BrowserThread::PostTask(
321 content::BrowserThread::UI, 414 content::BrowserThread::UI,
322 FROM_HERE, 415 FROM_HERE,
323 base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_)); 416 base::Bind(&CloseStorageAndDestroyTaskHelperOnUIThread, storage_name_));
324 delete this; 417 delete this;
325 } 418 }
326 419
420 void MTPDeviceDelegateImplLinux::GetFileInfoInternal(
421 const base::FilePath& file_path,
422 const GetFileInfoSuccessCallback& success_callback,
423 const ErrorCallback& error_callback) {
424 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
425
426 uint32 file_id;
427 if (CachedPathToId(file_path, &file_id)) {
428 GetFileInfoSuccessCallback success_callback_wrapper =
429 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfo,
430 weak_ptr_factory_.GetWeakPtr(),
431 success_callback);
432 ErrorCallback error_callback_wrapper =
433 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
434 weak_ptr_factory_.GetWeakPtr(),
435 error_callback,
436 file_id);
437
438
439 base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
440 storage_name_,
441 file_id,
442 success_callback_wrapper,
443 error_callback_wrapper);
444 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
445 content::BrowserThread::UI,
446 FROM_HERE,
447 closure));
448 } else {
449 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
450 }
451 PendingRequestDone();
452 }
453
454 void MTPDeviceDelegateImplLinux::ReadDirectoryInternal(
455 const base::FilePath& root,
456 const ReadDirectorySuccessCallback& success_callback,
457 const ErrorCallback& error_callback) {
458 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
459
460 uint32 dir_id;
461 if (CachedPathToId(root, &dir_id)) {
462 GetFileInfoSuccessCallback success_callback_wrapper =
463 base::Bind(&MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory,
464 weak_ptr_factory_.GetWeakPtr(),
465 dir_id,
466 success_callback,
467 error_callback);
468 ErrorCallback error_callback_wrapper =
469 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
470 weak_ptr_factory_.GetWeakPtr(),
471 error_callback,
472 dir_id);
473 base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
474 storage_name_,
475 dir_id,
476 success_callback_wrapper,
477 error_callback_wrapper);
478 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
479 content::BrowserThread::UI,
480 FROM_HERE,
481 closure));
482 } else {
483 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
484 }
485 PendingRequestDone();
486 }
487
488 void MTPDeviceDelegateImplLinux::CreateSnapshotFileInternal(
489 const base::FilePath& device_file_path,
490 const base::FilePath& local_path,
491 const CreateSnapshotFileSuccessCallback& success_callback,
492 const ErrorCallback& error_callback) {
493 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
494
495 uint32 file_id;
496 if (CachedPathToId(device_file_path, &file_id)) {
497 scoped_ptr<SnapshotRequestInfo> request_info(
498 new SnapshotRequestInfo(file_id,
499 local_path,
500 success_callback,
501 error_callback));
502 GetFileInfoSuccessCallback success_callback_wrapper =
503 base::Bind(
504 &MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile,
505 weak_ptr_factory_.GetWeakPtr(),
506 base::Passed(&request_info));
507 ErrorCallback error_callback_wrapper =
508 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
509 weak_ptr_factory_.GetWeakPtr(),
510 error_callback,
511 file_id);
512 base::Closure closure = base::Bind(&GetFileInfoOnUIThread,
513 storage_name_,
514 file_id,
515 success_callback_wrapper,
516 error_callback_wrapper);
517 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
518 content::BrowserThread::UI,
519 FROM_HERE,
520 closure));
521 } else {
522 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
523 }
524 PendingRequestDone();
525 }
526
527 void MTPDeviceDelegateImplLinux::ReadBytesInternal(
528 const base::FilePath& device_file_path,
529 net::IOBuffer* buf, int64 offset, int buf_len,
530 const ReadBytesSuccessCallback& success_callback,
531 const ErrorCallback& error_callback) {
532 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
533
534 uint32 file_id;
535 if (CachedPathToId(device_file_path, &file_id)) {
536 ReadBytesRequest request(
537 file_id, buf, offset, buf_len,
538 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadBytes,
539 weak_ptr_factory_.GetWeakPtr(),
540 success_callback),
541 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
542 weak_ptr_factory_.GetWeakPtr(),
543 error_callback,
544 file_id));
545
546 base::Closure closure =
547 base::Bind(base::Bind(&ReadBytesOnUIThread, storage_name_, request));
548 EnsureInitAndRunTask(PendingTaskInfo(base::FilePath(),
549 content::BrowserThread::UI,
550 FROM_HERE,
551 closure));
552 } else {
553 error_callback.Run(base::File::FILE_ERROR_NOT_FOUND);
554 }
555 PendingRequestDone();
556 }
557
327 void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask( 558 void MTPDeviceDelegateImplLinux::EnsureInitAndRunTask(
328 const PendingTaskInfo& task_info) { 559 const PendingTaskInfo& task_info) {
329 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 560 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
330 if ((init_state_ == INITIALIZED) && !task_in_progress_) { 561 if ((init_state_ == INITIALIZED) && !task_in_progress_) {
331 task_in_progress_ = true; 562 RunTask(task_info);
332 content::BrowserThread::PostTask(content::BrowserThread::UI,
333 task_info.location,
334 task_info.task);
335 return; 563 return;
336 } 564 }
337 pending_tasks_.push(task_info); 565
566 // Only *Internal functions have empty paths. Since they are the continuation
567 // of the current running task, they get to cut in line.
568 if (task_info.path.empty())
569 pending_tasks_.push_front(task_info);
570 else
571 pending_tasks_.push_back(task_info);
572
338 if (init_state_ == UNINITIALIZED) { 573 if (init_state_ == UNINITIALIZED) {
339 init_state_ = PENDING_INIT; 574 init_state_ = PENDING_INIT;
340 task_in_progress_ = true; 575 task_in_progress_ = true;
341 content::BrowserThread::PostTask( 576 content::BrowserThread::PostTask(
342 content::BrowserThread::UI, 577 content::BrowserThread::UI,
343 FROM_HERE, 578 FROM_HERE,
344 base::Bind(&OpenStorageOnUIThread, 579 base::Bind(&OpenStorageOnUIThread,
345 storage_name_, 580 storage_name_,
346 base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted, 581 base::Bind(&MTPDeviceDelegateImplLinux::OnInitCompleted,
347 weak_ptr_factory_.GetWeakPtr()))); 582 weak_ptr_factory_.GetWeakPtr())));
348 } 583 }
349 } 584 }
350 585
586 void MTPDeviceDelegateImplLinux::RunTask(const PendingTaskInfo& task_info) {
587 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
588 DCHECK_EQ(INITIALIZED, init_state_);
589 DCHECK(!task_in_progress_);
590 task_in_progress_ = true;
591
592 bool need_to_check_cache = !task_info.path.empty();
593 if (need_to_check_cache) {
594 base::FilePath uncached_path =
595 NextUncachedPathComponent(task_info.path, task_info.cached_path);
596 if (!uncached_path.empty()) {
597 // Save the current task and do a cache lookup first.
598 pending_tasks_.push_front(task_info);
599 FillFileCache(uncached_path);
600 return;
601 }
602 }
603
604 content::BrowserThread::PostTask(task_info.thread_id,
605 task_info.location,
606 task_info.task);
607 }
608
351 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile( 609 void MTPDeviceDelegateImplLinux::WriteDataIntoSnapshotFile(
352 const base::File::Info& file_info) { 610 const base::File::Info& file_info) {
353 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 611 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
354 DCHECK(current_snapshot_request_info_.get()); 612 DCHECK(current_snapshot_request_info_.get());
355 DCHECK_GT(file_info.size, 0); 613 DCHECK_GT(file_info.size, 0);
356 DCHECK(task_in_progress_); 614 DCHECK(task_in_progress_);
357 SnapshotRequestInfo request_info( 615 SnapshotRequestInfo request_info(
358 current_snapshot_request_info_->device_file_path, 616 current_snapshot_request_info_->file_id,
359 current_snapshot_request_info_->snapshot_file_path, 617 current_snapshot_request_info_->snapshot_file_path,
360 base::Bind( 618 base::Bind(
361 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile, 619 &MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile,
362 weak_ptr_factory_.GetWeakPtr()), 620 weak_ptr_factory_.GetWeakPtr()),
363 base::Bind( 621 base::Bind(
364 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError, 622 &MTPDeviceDelegateImplLinux::OnWriteDataIntoSnapshotFileError,
365 weak_ptr_factory_.GetWeakPtr())); 623 weak_ptr_factory_.GetWeakPtr()));
366 624
367 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread, 625 base::Closure task_closure = base::Bind(&WriteDataIntoSnapshotFileOnUIThread,
368 storage_name_, 626 storage_name_,
369 request_info, 627 request_info,
370 file_info); 628 file_info);
371 content::BrowserThread::PostTask(content::BrowserThread::UI, 629 content::BrowserThread::PostTask(content::BrowserThread::UI,
372 FROM_HERE, 630 FROM_HERE,
373 task_closure); 631 task_closure);
374 } 632 }
375 633
376 void MTPDeviceDelegateImplLinux::PendingRequestDone() { 634 void MTPDeviceDelegateImplLinux::PendingRequestDone() {
377 DCHECK(task_in_progress_); 635 DCHECK(task_in_progress_);
378 task_in_progress_ = false; 636 task_in_progress_ = false;
379 ProcessNextPendingRequest(); 637 ProcessNextPendingRequest();
380 } 638 }
381 639
382 void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() { 640 void MTPDeviceDelegateImplLinux::ProcessNextPendingRequest() {
383 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 641 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
384 DCHECK(!task_in_progress_); 642 DCHECK(!task_in_progress_);
385 if (pending_tasks_.empty()) 643 if (pending_tasks_.empty())
386 return; 644 return;
387 645
388 task_in_progress_ = true; 646 PendingTaskInfo task_info = pending_tasks_.front();
389 const PendingTaskInfo& task_info = pending_tasks_.front(); 647 pending_tasks_.pop_front();
390 content::BrowserThread::PostTask(content::BrowserThread::UI, 648 RunTask(task_info);
391 task_info.location,
392 task_info.task);
393 pending_tasks_.pop();
394 } 649 }
395 650
396 void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) { 651 void MTPDeviceDelegateImplLinux::OnInitCompleted(bool succeeded) {
397 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 652 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
398 init_state_ = succeeded ? INITIALIZED : UNINITIALIZED; 653 init_state_ = succeeded ? INITIALIZED : UNINITIALIZED;
399 PendingRequestDone(); 654 PendingRequestDone();
400 } 655 }
401 656
402 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo( 657 void MTPDeviceDelegateImplLinux::OnDidGetFileInfo(
403 const GetFileInfoSuccessCallback& success_callback, 658 const GetFileInfoSuccessCallback& success_callback,
404 const base::File::Info& file_info) { 659 const base::File::Info& file_info) {
405 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 660 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
406 success_callback.Run(file_info); 661 success_callback.Run(file_info);
407 PendingRequestDone(); 662 PendingRequestDone();
408 } 663 }
409 664
410 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory( 665 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToReadDirectory(
411 const std::string& root, 666 uint32 dir_id,
412 const ReadDirectorySuccessCallback& success_callback, 667 const ReadDirectorySuccessCallback& success_callback,
413 const ErrorCallback& error_callback, 668 const ErrorCallback& error_callback,
414 const base::File::Info& file_info) { 669 const base::File::Info& file_info) {
415 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 670 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
416 DCHECK(task_in_progress_); 671 DCHECK(task_in_progress_);
417 if (!file_info.is_directory) { 672 if (!file_info.is_directory) {
418 return HandleDeviceFileError(error_callback, 673 return HandleDeviceFileError(error_callback,
674 dir_id,
419 base::File::FILE_ERROR_NOT_A_DIRECTORY); 675 base::File::FILE_ERROR_NOT_A_DIRECTORY);
420 } 676 }
421 677
422 base::Closure task_closure = 678 base::Closure task_closure =
423 base::Bind(&ReadDirectoryOnUIThread, 679 base::Bind(&ReadDirectoryOnUIThread,
424 storage_name_, 680 storage_name_,
425 root, 681 dir_id,
426 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory, 682 base::Bind(&MTPDeviceDelegateImplLinux::OnDidReadDirectory,
427 weak_ptr_factory_.GetWeakPtr(), 683 weak_ptr_factory_.GetWeakPtr(),
684 dir_id,
428 success_callback), 685 success_callback),
429 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError, 686 base::Bind(&MTPDeviceDelegateImplLinux::HandleDeviceFileError,
430 weak_ptr_factory_.GetWeakPtr(), 687 weak_ptr_factory_.GetWeakPtr(),
431 error_callback)); 688 error_callback,
689 dir_id));
432 content::BrowserThread::PostTask(content::BrowserThread::UI, 690 content::BrowserThread::PostTask(content::BrowserThread::UI,
433 FROM_HERE, 691 FROM_HERE,
434 task_closure); 692 task_closure);
435 } 693 }
436 694
437 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile( 695 void MTPDeviceDelegateImplLinux::OnDidGetFileInfoToCreateSnapshotFile(
438 scoped_ptr<SnapshotRequestInfo> snapshot_request_info, 696 scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
439 const base::File::Info& file_info) { 697 const base::File::Info& file_info) {
440 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 698 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
441 DCHECK(!current_snapshot_request_info_.get()); 699 DCHECK(!current_snapshot_request_info_.get());
442 DCHECK(snapshot_request_info.get()); 700 DCHECK(snapshot_request_info.get());
443 DCHECK(task_in_progress_); 701 DCHECK(task_in_progress_);
444 base::File::Error error = base::File::FILE_OK; 702 base::File::Error error = base::File::FILE_OK;
445 if (file_info.is_directory) 703 if (file_info.is_directory)
446 error = base::File::FILE_ERROR_NOT_A_FILE; 704 error = base::File::FILE_ERROR_NOT_A_FILE;
447 else if (file_info.size < 0 || file_info.size > kuint32max) 705 else if (file_info.size < 0 || file_info.size > kuint32max)
448 error = base::File::FILE_ERROR_FAILED; 706 error = base::File::FILE_ERROR_FAILED;
449 707
450 if (error != base::File::FILE_OK) 708 if (error != base::File::FILE_OK)
451 return HandleDeviceFileError(snapshot_request_info->error_callback, error); 709 return HandleDeviceFileError(snapshot_request_info->error_callback,
710 snapshot_request_info->file_id,
711 error);
452 712
453 base::File::Info snapshot_file_info(file_info); 713 base::File::Info snapshot_file_info(file_info);
454 // Modify the last modified time to null. This prevents the time stamp 714 // Modify the last modified time to null. This prevents the time stamp
455 // verfication in LocalFileStreamReader. 715 // verfication in LocalFileStreamReader.
456 snapshot_file_info.last_modified = base::Time(); 716 snapshot_file_info.last_modified = base::Time();
457 717
458 current_snapshot_request_info_.reset(snapshot_request_info.release()); 718 current_snapshot_request_info_.reset(snapshot_request_info.release());
459 if (file_info.size == 0) { 719 if (file_info.size == 0) {
460 // Empty snapshot file. 720 // Empty snapshot file.
461 return OnDidWriteDataIntoSnapshotFile( 721 return OnDidWriteDataIntoSnapshotFile(
462 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path); 722 snapshot_file_info, current_snapshot_request_info_->snapshot_file_path);
463 } 723 }
464 WriteDataIntoSnapshotFile(snapshot_file_info); 724 WriteDataIntoSnapshotFile(snapshot_file_info);
465 } 725 }
466 726
467 void MTPDeviceDelegateImplLinux::OnDidReadDirectory( 727 void MTPDeviceDelegateImplLinux::OnDidReadDirectory(
728 uint32 dir_id,
468 const ReadDirectorySuccessCallback& success_callback, 729 const ReadDirectorySuccessCallback& success_callback,
469 const fileapi::AsyncFileUtil::EntryList& file_list) { 730 const fileapi::AsyncFileUtil::EntryList& file_list) {
470 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 731 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
471 success_callback.Run(file_list, false /*no more entries*/); 732
733 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(dir_id);
734 DCHECK(it != file_id_to_node_map_.end());
735 MTPFileNode* dir_node = it->second;
736 std::set<std::string> children_to_keep;
737
738 fileapi::AsyncFileUtil::EntryList normalized_file_list;
739 for (size_t i = 0; i < file_list.size(); ++i) {
740 normalized_file_list.push_back(file_list[i]);
741 fileapi::DirectoryEntry& entry = normalized_file_list.back();
742
743 // |entry.name| has the file id encoded in it. Decode here.
744 size_t separator_idx = entry.name.find_last_of(',');
745 DCHECK_NE(std::string::npos, separator_idx);
746 std::string file_id_str = entry.name.substr(separator_idx);
747 file_id_str = file_id_str.substr(1); // Get rid of the comma.
748 uint32 file_id = 0;
749 bool ret = base::StringToUint(file_id_str, &file_id);
750 DCHECK(ret);
751 entry.name = entry.name.substr(0, separator_idx);
752
753 // Refresh the in memory tree.
754 dir_node->EnsureChildExists(entry.name, file_id);
755 children_to_keep.insert(entry.name);
756 }
757 dir_node->ClearNonexistentChildren(children_to_keep);
758
759 success_callback.Run(normalized_file_list, false /*no more entries*/);
472 PendingRequestDone(); 760 PendingRequestDone();
473 } 761 }
474 762
475 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile( 763 void MTPDeviceDelegateImplLinux::OnDidWriteDataIntoSnapshotFile(
476 const base::File::Info& file_info, 764 const base::File::Info& file_info,
477 const base::FilePath& snapshot_file_path) { 765 const base::FilePath& snapshot_file_path) {
478 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 766 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
479 DCHECK(current_snapshot_request_info_.get()); 767 DCHECK(current_snapshot_request_info_.get());
480 current_snapshot_request_info_->success_callback.Run( 768 current_snapshot_request_info_->success_callback.Run(
481 file_info, snapshot_file_path); 769 file_info, snapshot_file_path);
(...skipping 11 matching lines...) Expand all
493 } 781 }
494 782
495 void MTPDeviceDelegateImplLinux::OnDidReadBytes( 783 void MTPDeviceDelegateImplLinux::OnDidReadBytes(
496 const ReadBytesSuccessCallback& success_callback, 784 const ReadBytesSuccessCallback& success_callback,
497 const base::File::Info& file_info, int bytes_read) { 785 const base::File::Info& file_info, int bytes_read) {
498 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 786 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
499 success_callback.Run(file_info, bytes_read); 787 success_callback.Run(file_info, bytes_read);
500 PendingRequestDone(); 788 PendingRequestDone();
501 } 789 }
502 790
791 void MTPDeviceDelegateImplLinux::OnDidFillFileCache(
792 const base::FilePath& path,
793 const fileapi::AsyncFileUtil::EntryList& /* file_list */,
794 bool /* has_more */) {
795 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
796 DCHECK(path.IsParent(pending_tasks_.front().path));
797 pending_tasks_.front().cached_path = path;
798 }
799
800 void MTPDeviceDelegateImplLinux::OnFillFileCacheFailed(
801 base::File::Error /* error */) {
802 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
803 // When filling the cache fails for the task at the front of the queue, clear
804 // the path of the task so it will not try to do any more caching. Instead,
805 // the task will just run and fail the CachedPathToId() lookup.
806 pending_tasks_.front().path.clear();
807 }
808
503 void MTPDeviceDelegateImplLinux::HandleDeviceFileError( 809 void MTPDeviceDelegateImplLinux::HandleDeviceFileError(
504 const ErrorCallback& error_callback, 810 const ErrorCallback& error_callback,
811 uint32 file_id,
505 base::File::Error error) { 812 base::File::Error error) {
506 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 813 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
814
815 FileIdToMTPFileNodeMap::iterator it = file_id_to_node_map_.find(file_id);
816 if (it != file_id_to_node_map_.end()) {
817 MTPFileNode* parent = it->second->parent();
818 if (parent) {
819 bool ret = parent->DeleteChild(file_id);
820 DCHECK(ret);
821 }
822 }
507 error_callback.Run(error); 823 error_callback.Run(error);
508 PendingRequestDone(); 824 PendingRequestDone();
509 } 825 }
510 826
827 base::FilePath MTPDeviceDelegateImplLinux::NextUncachedPathComponent(
828 const base::FilePath& path,
829 const base::FilePath& cached_path) const {
830 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
831 DCHECK(cached_path.empty() || cached_path.IsParent(path));
832
833 base::FilePath uncached_path;
834 std::string device_relpath = GetDeviceRelativePath(device_path_, path);
835 if (!device_relpath.empty() && device_relpath != kRootPath) {
836 uncached_path = device_path_;
837 std::vector<std::string> device_relpath_components;
838 base::SplitString(device_relpath, '/', &device_relpath_components);
839 DCHECK(!device_relpath_components.empty());
840 bool all_components_cached = true;
841 const MTPFileNode* current_node = root_node_.get();
842 for (size_t i = 0; i < device_relpath_components.size(); ++i) {
843 current_node = current_node->GetChild(device_relpath_components[i]);
844 if (!current_node) {
845 // With a cache miss, check if it is a genuine failure. If so, pretend
846 // the entire |path| is cached, so there is no further attempt to do
847 // more caching. The actual operation will then fail.
848 all_components_cached =
849 !cached_path.empty() && (uncached_path == cached_path);
850 break;
851 }
852 uncached_path = uncached_path.Append(device_relpath_components[i]);
853 }
854 if (all_components_cached)
855 uncached_path.clear();
856 }
857 return uncached_path;
858 }
859
860 void MTPDeviceDelegateImplLinux::FillFileCache(
861 const base::FilePath& uncached_path) {
862 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
863 DCHECK(task_in_progress_);
864
865 ReadDirectorySuccessCallback success_callback =
866 base::Bind(&MTPDeviceDelegateImplLinux::OnDidFillFileCache,
867 weak_ptr_factory_.GetWeakPtr(),
868 uncached_path);
869 ErrorCallback error_callback =
870 base::Bind(&MTPDeviceDelegateImplLinux::OnFillFileCacheFailed,
871 weak_ptr_factory_.GetWeakPtr());
872 ReadDirectoryInternal(uncached_path, success_callback, error_callback);
873 }
874
875
876 bool MTPDeviceDelegateImplLinux::CachedPathToId(const base::FilePath& path,
877 uint32* id) const {
878 DCHECK(id);
879
880 std::string device_relpath = GetDeviceRelativePath(device_path_, path);
881 if (device_relpath.empty())
882 return false;
883 std::vector<std::string> device_relpath_components;
884 if (device_relpath != kRootPath)
885 base::SplitString(device_relpath, '/', &device_relpath_components);
886 const MTPFileNode* current_node = root_node_.get();
887 for (size_t i = 0; i < device_relpath_components.size(); ++i) {
888 current_node = current_node->GetChild(device_relpath_components[i]);
889 if (!current_node)
890 return false;
891 }
892 *id = current_node->file_id();
893 return true;
894 }
895
511 void CreateMTPDeviceAsyncDelegate( 896 void CreateMTPDeviceAsyncDelegate(
512 const std::string& device_location, 897 const std::string& device_location,
513 const CreateMTPDeviceAsyncDelegateCallback& callback) { 898 const CreateMTPDeviceAsyncDelegateCallback& callback) {
514 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 899 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
515 callback.Run(new MTPDeviceDelegateImplLinux(device_location)); 900 callback.Run(new MTPDeviceDelegateImplLinux(device_location));
516 } 901 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698