Home | History | Annotate | Download | only in linux
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
      6 #define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
      7 
      8 #include <queue>
      9 
     10 #include "base/callback.h"
     11 #include "base/location.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/platform_file.h"
     15 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
     16 #include "chrome/browser/media_galleries/mtp_device_delegate_impl.h"
     17 #include "webkit/browser/fileapi/async_file_util.h"
     18 
     19 namespace base {
     20 class FilePath;
     21 }
     22 
     23 namespace chrome {
     24 
     25 struct SnapshotRequestInfo;
     26 
     27 // MTPDeviceDelegateImplLinux communicates with the media transfer protocol
     28 // (MTP) device to complete file system operations. These operations are
     29 // performed asynchronously. Instantiate this class per MTP device storage.
     30 // MTPDeviceDelegateImplLinux lives on the IO thread.
     31 // MTPDeviceDelegateImplLinux does a call-and-reply to the UI thread
     32 // to dispatch the requests to MediaTransferProtocolManager.
     33 class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
     34  private:
     35   friend void CreateMTPDeviceAsyncDelegate(
     36       const std::string&,
     37       const CreateMTPDeviceAsyncDelegateCallback&);
     38 
     39   enum InitializationState {
     40     UNINITIALIZED = 0,
     41     PENDING_INIT,
     42     INITIALIZED
     43   };
     44 
     45   // Used to represent pending task details.
     46   struct PendingTaskInfo {
     47     PendingTaskInfo(const tracked_objects::Location& location,
     48                     const base::Closure& task);
     49     ~PendingTaskInfo();
     50 
     51     const tracked_objects::Location location;
     52     const base::Closure task;
     53   };
     54 
     55   // Should only be called by CreateMTPDeviceAsyncDelegate() factory call.
     56   // Defer the device initializations until the first file operation request.
     57   // Do all the initializations in EnsureInitAndRunTask() function.
     58   explicit MTPDeviceDelegateImplLinux(const std::string& device_location);
     59 
     60   // Destructed via CancelPendingTasksAndDeleteDelegate().
     61   virtual ~MTPDeviceDelegateImplLinux();
     62 
     63   // MTPDeviceAsyncDelegate:
     64   virtual void GetFileInfo(const base::FilePath& file_path,
     65                            const GetFileInfoSuccessCallback& success_callback,
     66                            const ErrorCallback& error_callback) OVERRIDE;
     67   virtual void ReadDirectory(
     68       const base::FilePath& root,
     69       const ReadDirectorySuccessCallback& success_callback,
     70       const ErrorCallback& error_callback) OVERRIDE;
     71   virtual void CreateSnapshotFile(
     72       const base::FilePath& device_file_path,
     73       const base::FilePath& local_path,
     74       const CreateSnapshotFileSuccessCallback& success_callback,
     75       const ErrorCallback& error_callback) OVERRIDE;
     76   virtual void CancelPendingTasksAndDeleteDelegate() OVERRIDE;
     77 
     78   // Ensures the device is initialized for communication by doing a
     79   // call-and-reply to the UI thread. |task_info.task| runs on the UI thread.
     80   //
     81   // If the device is already initialized, post the |task_info.task| immediately
     82   // on the UI thread.
     83   //
     84   // If the device is uninitialized, store the |task_info| in a pending task
     85   // list and runs all the pending tasks once the device is successfully
     86   // initialized.
     87   void EnsureInitAndRunTask(const PendingTaskInfo& task_info);
     88 
     89   // Writes data from the device to the snapshot file path based on the
     90   // parameters in |current_snapshot_request_info_| by doing a call-and-reply to
     91   // the UI thread.
     92   //
     93   // |snapshot_file_info| specifies the metadata details of the snapshot file.
     94   void WriteDataIntoSnapshotFile(
     95       const base::PlatformFileInfo& snapshot_file_info);
     96 
     97   // Processes the next pending request.
     98   void ProcessNextPendingRequest();
     99 
    100   // Handles the device initialization event. |succeeded| indicates whether
    101   // device initialization succeeded.
    102   //
    103   // If the device is successfully initialized, runs the next pending task.
    104   void OnInitCompleted(bool succeeded);
    105 
    106   // Called when GetFileInfo() succeeds. |file_info| specifies the
    107   // requested file details. |success_callback| is invoked to notify the caller
    108   // about the requested file details.
    109   void OnDidGetFileInfo(const GetFileInfoSuccessCallback& success_callback,
    110                         const base::PlatformFileInfo& file_info);
    111 
    112   // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to
    113   // get the |root| directory metadata details. |file_info| specifies the |root|
    114   // directory details.
    115   //
    116   // If |root| is a directory, post a task on the UI thread to read the |root|
    117   // directory file entries.
    118   //
    119   // If |root| is not a directory, |error_callback| is invoked to notify the
    120   // caller about the platform file error and process the next pending request.
    121   void OnDidGetFileInfoToReadDirectory(
    122       const std::string& root,
    123       const ReadDirectorySuccessCallback& success_callback,
    124       const ErrorCallback& error_callback,
    125       const base::PlatformFileInfo& file_info);
    126 
    127   // Called when GetFileInfo() succeeds. GetFileInfo() is invoked to
    128   // create the snapshot file of |snapshot_request_info.device_file_path|.
    129   // |file_info| specifies the device file metadata details.
    130   //
    131   // Posts a task on the UI thread to copy the data contents of the device file
    132   // to the snapshot file.
    133   void OnDidGetFileInfoToCreateSnapshotFile(
    134       scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
    135       const base::PlatformFileInfo& file_info);
    136 
    137   // Called when ReadDirectory() succeeds.
    138   //
    139   // |file_list| contains the directory file entries.
    140   // |success_callback| is invoked to notify the caller about the directory
    141   // file entries.
    142   void OnDidReadDirectory(const ReadDirectorySuccessCallback& success_callback,
    143                           const fileapi::AsyncFileUtil::EntryList& file_list);
    144 
    145   // Called when WriteDataIntoSnapshotFile() succeeds.
    146   //
    147   // |snapshot_file_info| specifies the snapshot file metadata details.
    148   //
    149   // |current_snapshot_request_info_.success_callback| is invoked to notify the
    150   // caller about |snapshot_file_info|.
    151   void OnDidWriteDataIntoSnapshotFile(
    152       const base::PlatformFileInfo& snapshot_file_info,
    153       const base::FilePath& snapshot_file_path);
    154 
    155   // Called when WriteDataIntoSnapshotFile() fails.
    156   //
    157   // |error| specifies the platform file error code.
    158   //
    159   // |current_snapshot_request_info_.error_callback| is invoked to notify the
    160   // caller about |error|.
    161   void OnWriteDataIntoSnapshotFileError(base::PlatformFileError error);
    162 
    163   // Handles the device file |error|. |error_callback| is invoked to notify the
    164   // caller about the file error.
    165   void HandleDeviceFileError(const ErrorCallback& error_callback,
    166                              base::PlatformFileError error);
    167 
    168   // MTP device initialization state.
    169   InitializationState init_state_;
    170 
    171   // Used to make sure only one task is in progress at any time.
    172   bool task_in_progress_;
    173 
    174   // Registered file system device path. This path does not
    175   // correspond to a real device path (e.g. "/usb:2,2:81282").
    176   const base::FilePath device_path_;
    177 
    178   // MTP device storage name (e.g. "usb:2,2:81282").
    179   std::string storage_name_;
    180 
    181   // A list of pending tasks that needs to be run when the device is
    182   // initialized or when the current task in progress is complete.
    183   std::queue<PendingTaskInfo> pending_tasks_;
    184 
    185   // Used to track the current snapshot file request. A snapshot file is created
    186   // incrementally. CreateSnapshotFile request reads the device file and writes
    187   // to the snapshot file in chunks. In order to retain the order of the
    188   // snapshot file requests, make sure there is only one active snapshot file
    189   // request at any time.
    190   scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_;
    191 
    192   // For callbacks that may run after destruction.
    193   base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_;
    194 
    195   DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux);
    196 };
    197 
    198 }  // namespace chrome
    199 
    200 #endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
    201