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

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: 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 <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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698