| 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 <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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |