Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / media_galleries / linux / mtp_device_delegate_impl_linux.h
index 1534b0d..44d390d 100644 (file)
@@ -5,20 +5,21 @@
 #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 <deque>
+#include <map>
+#include <set>
+#include <string>
 
 #include "base/callback.h"
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/files/file_path.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 "content/public/browser/browser_thread.h"
 #include "webkit/browser/fileapi/async_file_util.h"
 
-namespace base {
-class FilePath;
-}
-
 struct SnapshotRequestInfo;
 
 // MTPDeviceDelegateImplLinux communicates with the media transfer protocol
@@ -41,14 +42,24 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
 
   // Used to represent pending task details.
   struct PendingTaskInfo {
-    PendingTaskInfo(const tracked_objects::Location& location,
+    PendingTaskInfo(const base::FilePath& path,
+                    content::BrowserThread::ID thread_id,
+                    const tracked_objects::Location& location,
                     const base::Closure& task);
     ~PendingTaskInfo();
 
+    base::FilePath path;
+    base::FilePath cached_path;
+    const content::BrowserThread::ID thread_id;
     const tracked_objects::Location location;
     const base::Closure task;
   };
 
+  class MTPFileNode;
+
+  // Maps file ids to file nodes.
+  typedef std::map<uint32, MTPFileNode*> FileIdToMTPFileNodeMap;
+
   // 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.
@@ -78,17 +89,41 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
       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.
+  // The internal methods correspond to the similarly named methods above.
+  // The |root_node_| cache should be filled at this point.
+  virtual void GetFileInfoInternal(
+      const base::FilePath& file_path,
+      const GetFileInfoSuccessCallback& success_callback,
+      const ErrorCallback& error_callback);
+  virtual void ReadDirectoryInternal(
+      const base::FilePath& root,
+      const ReadDirectorySuccessCallback& success_callback,
+      const ErrorCallback& error_callback);
+  virtual void CreateSnapshotFileInternal(
+      const base::FilePath& device_file_path,
+      const base::FilePath& local_path,
+      const CreateSnapshotFileSuccessCallback& success_callback,
+      const ErrorCallback& error_callback);
+  virtual void ReadBytesInternal(
+      const base::FilePath& device_file_path,
+      net::IOBuffer* buf, int64 offset, int buf_len,
+      const ReadBytesSuccessCallback& success_callback,
+      const ErrorCallback& error_callback);
+
+  // Ensures the device is initialized for communication.
+  // If the device is already initialized, call RunTask().
   //
   // 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.
+  // queue and runs the pending tasks in the queue once the device is
+  // successfully initialized.
   void EnsureInitAndRunTask(const PendingTaskInfo& task_info);
 
+  // Runs a task. If |task_info.path| is empty, or if the path is cached, runs
+  // the task immediately.
+  // Otherwise, fills the cache first before running the task.
+  // |task_info.task| runs on the UI thread.
+  void RunTask(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.
@@ -96,6 +131,9 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
   // |snapshot_file_info| specifies the metadata details of the snapshot file.
   void WriteDataIntoSnapshotFile(const base::File::Info& snapshot_file_info);
 
+  // Marks the current request as complete and call ProcessNextPendingRequest().
+  void PendingRequestDone();
+
   // Processes the next pending request.
   void ProcessNextPendingRequest();
 
@@ -112,16 +150,16 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
                         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.
+  // get the |dir_id| directory metadata details. |file_info| specifies the
+  // |dir_id| directory details.
   //
-  // If |root| is a directory, post a task on the UI thread to read the |root|
-  // directory file entries.
+  // If |dir_id| is a directory, post a task on the UI thread to read the
+  // |dir_id| 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.
+  // If |dir_id| is not a directory, |error_callback| is invoked to notify the
+  // caller about the file error and process the next pending request.
   void OnDidGetFileInfoToReadDirectory(
-      const std::string& root,
+      uint32 dir_id,
       const ReadDirectorySuccessCallback& success_callback,
       const ErrorCallback& error_callback,
       const base::File::Info& file_info);
@@ -136,17 +174,17 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
       scoped_ptr<SnapshotRequestInfo> snapshot_request_info,
       const base::File::Info& file_info);
 
-  // Called when GetFileInfo() succeeds to read a range of bytes.
-  void OnDidGetFileInfoToReadBytes(const ReadBytesRequest& request,
-                                   const base::File::Info& file_info);
-
   // Called when ReadDirectory() succeeds.
   //
-  // |file_list| contains the directory file entries.
+  // |dir_id| is the directory read.
   // |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);
+  // |file_list| contains the directory file entries with their file ids.
+  // |has_more| is true if there are more file entries to read.
+  void OnDidReadDirectory(uint32 dir_id,
+                          const ReadDirectorySuccessCallback& success_callback,
+                          const fileapi::AsyncFileUtil::EntryList& file_list,
+                          bool has_more);
 
   // Called when WriteDataIntoSnapshotFile() succeeds.
   //
@@ -160,7 +198,7 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
 
   // Called when WriteDataIntoSnapshotFile() fails.
   //
-  // |error| specifies the platform file error code.
+  // |error| specifies the file error code.
   //
   // |current_snapshot_request_info_.error_callback| is invoked to notify the
   // caller about |error|.
@@ -171,17 +209,42 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
   // |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,
-                      int bytes_read);
+                      const base::File::Info& file_info, int bytes_read);
+
+  // Called when FillFileCache() succeeds.
+  void OnDidFillFileCache(const base::FilePath& path,
+                          const fileapi::AsyncFileUtil::EntryList& file_list,
+                          bool has_more);
+
+  // Called when FillFileCache() fails.
+  void OnFillFileCacheFailed(base::File::Error error);
 
-  // Handles the device file |error|. |error_callback| is invoked to notify the
-  // caller about the file error.
+  // Handles the device file |error| while operating on |file_id|.
+  // |error_callback| is invoked to notify the caller about the file error.
   void HandleDeviceFileError(const ErrorCallback& error_callback,
+                             uint32 file_id,
                              base::File::Error error);
 
+  // Given a full path, returns a non-empty sub-path that needs to be read into
+  // the cache if such a uncached path exists.
+  // |cached_path| is the portion of |path| that has had cache lookup attempts.
+  base::FilePath NextUncachedPathComponent(
+      const base::FilePath& path,
+      const base::FilePath& cached_path) const;
+
+  // Fills the file cache using the results from NextUncachedPathComponent().
+  void FillFileCache(const base::FilePath& uncached_path);
+
+  // Given a full path, if it exists in the cache, writes the file's id to |id|
+  // and return true.
+  bool CachedPathToId(const base::FilePath& path, uint32* id) const;
+
   // MTP device initialization state.
   InitializationState init_state_;
 
   // Used to make sure only one task is in progress at any time.
+  // Otherwise the browser will try to send too many requests at once and
+  // overload the device.
   bool task_in_progress_;
 
   // Registered file system device path. This path does not
@@ -193,7 +256,7 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
 
   // 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_;
+  std::deque<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
@@ -202,6 +265,19 @@ class MTPDeviceDelegateImplLinux : public MTPDeviceAsyncDelegate {
   // request at any time.
   scoped_ptr<SnapshotRequestInfo> current_snapshot_request_info_;
 
+  // A mapping for quick lookups into the |root_node_| tree structure. Since
+  // |root_node_| contains pointers to this map, it must be declared after this
+  // so destruction happens in the right order.
+  FileIdToMTPFileNodeMap file_id_to_node_map_;
+
+  // The root node of a tree-structure that caches the directory structure of
+  // the MTP device.
+  scoped_ptr<MTPFileNode> root_node_;
+
+  // A list of child nodes encountered while a ReadDirectory operation, which
+  // can return results over multiple callbacks, is in progress.
+  std::set<std::string> child_nodes_seen_;
+
   // For callbacks that may run after destruction.
   base::WeakPtrFactory<MTPDeviceDelegateImplLinux> weak_ptr_factory_;