Chromium Code Reviews| 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 |