// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ #define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_ #include <queue> #include "base/callback.h" #include "base/location.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/platform_file.h" #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h" #include "webkit/browser/fileapi/async_file_util.h" namespace base { class FilePath; } struct SnapshotRequestInfo; // MTPDeviceDelegateImplLinux communicates with the media transfer protocol // (MTP) device to complete file system operations. These operations are // performed asynchronously. Instantiate this class per MTP device storage. // MTPDeviceDelegateImplLinux lives on the IO thread. // MTPDeviceDelegateImplLinux does a call-and-reply to the UI thread // to dispatch the requests to MediaTransferProtocolManager. class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate { private: friend void CreateMTPDeviceAsyncDelegate( const std::string&, const CreateMTPDeviceAsyncDelegateCallback&); enum InitializationState { UNINITIALIZED = 0, PENDING_INIT, INITIALIZED }; // Used to represent pending task details. struct PendingTaskInfo { PendingTaskInfo(const tracked_objects::Location& location, const base::Closure& task); ~PendingTaskInfo(); const tracked_objects::Location location; const base::Closure task; }; // Should only be called by CreateMTPDeviceAsyncDelegate() factory call. // Defer the device initializations until the first file operation request. // Do all the initializations in EnsureInitAndRunTask() function. explicit MTPDeviceDelegateImplLinux(const std::string& device_location); // Destructed via CancelPendingTasksAndDeleteDelegate(). virtual ~MTPDeviceDelegateImplLinux(); // MTPDeviceAsyncDelegate: virtual void GetFileInfo(const base::FilePath& file_path, const GetFileInfoSuccessCallback& success_callback, const ErrorCallback& error_callback) OVERRIDE; virtual void ReadDirectory( const base::FilePath& root, const ReadDirectorySuccessCallback& success_callback, const ErrorCallback& error_callback) OVERRIDE; virtual void CreateSnapshotFile( const base::FilePath& device_file_path, const base::FilePath& local_path, const CreateSnapshotFileSuccessCallback& success_callback, const ErrorCallback& error_callback) OVERRIDE; virtual bool IsStreaming() OVERRIDE; virtual void ReadBytes( const base::FilePath& device_file_path, net::IOBuffer* buf, int64 offset, int buf_len, const ReadBytesSuccessCallback& success_callback, const ErrorCallback& error_callback) OVERRIDE; virtual void CancelPendingTasksAndDeleteDelegate() OVERRIDE; // Ensures the device is initialized for communication by doing a // call-and-reply to the UI thread. |task_info.task| runs on the UI thread. // // If the device is already initialized, post the |task_info.task| immediately // on the UI thread. // // If the device is uninitialized, store the |task_info| in a pending task // list and runs all the pending tasks once the device is successfully // initialized. void EnsureInitAndRunTask(const PendingTaskInfo& task_info); // Writes data from the device to the snapshot file path based on the // parameters in |current_snapshot_request_info_| by doing a call-and-reply to // the UI thread. // // |snapshot_file_info| specifies the metadata details of the snapshot file. void WriteDataIntoSnapshotFile(const base::File::Info& snapshot_file_info); // Processes the next pending request. void ProcessNextPendingRequest(); // Handles the device initialization event. |succeeded| indicates whether // device initialization succeeded. // // If the device is successfully initialized, runs the next pending task. void OnInitCompleted(bool succeeded); // Called when GetFileInfo() succeeds. |file_info| specifies the // requested file details. |success_callback| is invoked to notify the caller // about the requested file details. void OnDidGetFileInfo(const GetFileInfoSuccessCallback& success_callback, const base::File::Info& file_info); // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to // get the |root| directory metadata details. |file_info| specifies the |root| // directory details. // // If |root| is a directory, post a task on the UI thread to read the |root| // directory file entries. // // If |root| is not a directory, |error_callback| is invoked to notify the // caller about the platform file error and process the next pending request. void OnDidGetFileInfoToReadDirectory( const std::string& root, const ReadDirectorySuccessCallback& success_callback, const ErrorCallback& error_callback, const base::File::Info& file_info); // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to // create the snapshot file of |snapshot_request_info.device_file_path|. // |file_info| specifies the device file metadata details. // // Posts a task on the UI thread to copy the data contents of the device file // to the snapshot file. void OnDidGetFileInfoToCreateSnapshotFile( scoped_ptr<SnapshotRequestInfo> snapshot_request_info, const base::File::Info& file_info); // Called when ReadDirectory() succeeds. // // |file_list| contains the directory file entries. // |success_callback| is invoked to notify the caller about the directory // file entries. void OnDidReadDirectory(const ReadDirectorySuccessCallback& success_callback, const fileapi::AsyncFileUtil::EntryList& file_list); // Called when WriteDataIntoSnapshotFile() succeeds. // // |snapshot_file_info| specifies the snapshot file metadata details. // // |current_snapshot_request_info_.success_callback| is invoked to notify the // caller about |snapshot_file_info|. void OnDidWriteDataIntoSnapshotFile( const base::File::Info& snapshot_file_info, const base::FilePath& snapshot_file_path); // Called when WriteDataIntoSnapshotFile() fails. // // |error| specifies the platform file error code. // // |current_snapshot_request_info_.error_callback| is invoked to notify the // caller about |error|. void OnWriteDataIntoSnapshotFileError(base::File::Error error); // Called when ReadBytes() succeeds. // // |success_callback| is invoked to notify the caller about the read bytes. // |bytes_read| is the number of bytes read. void OnDidReadBytes(const ReadBytesSuccessCallback& success_callback, const base::File::Info& file_info, int bytes_read); // Handles the device file |error|. |error_callback| is invoked to notify the // caller about the file error. void HandleDeviceFileError(const ErrorCallback& error_callback, base::File::Error error); // MTP device initialization state. InitializationState init_state_; // Used to make sure only one task is in progress at any time. bool task_in_progress_; // Registered file system device path. This path does not // correspond to a real device path (e.g. "/usb:2,2:81282"). const base::FilePath device_path_; // MTP device storage name (e.g. "usb:2,2:81282"). std::string storage_name_; // A list of pending tasks that needs to be run when the device is // initialized or when the current task in progress is complete. std::queue<PendingTaskInfo> pending_tasks_; // Used to track the current snapshot file request. A snapshot file is created // incrementally. CreateSnapshotFile request reads the device file and writes // to the snapshot file in chunks. In order to retain the order of the // snapshot file requests, make sure there is only one active snapshot file // request at any time. scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_; // For callbacks that may run after destruction. base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux); }; #endif // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_