Home | History | Annotate | Download | only in proxy
      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 PPAPI_PROXY_FILE_IO_RESOURCE_H_
      6 #define PPAPI_PROXY_FILE_IO_RESOURCE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/memory/ref_counted.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "ppapi/c/private/pp_file_handle.h"
     13 #include "ppapi/proxy/connection.h"
     14 #include "ppapi/proxy/plugin_resource.h"
     15 #include "ppapi/proxy/ppapi_proxy_export.h"
     16 #include "ppapi/shared_impl/file_io_state_manager.h"
     17 #include "ppapi/shared_impl/resource.h"
     18 #include "ppapi/shared_impl/scoped_pp_resource.h"
     19 #include "ppapi/thunk/ppb_file_io_api.h"
     20 
     21 namespace ppapi {
     22 
     23 class TrackedCallback;
     24 
     25 namespace proxy {
     26 
     27 class PPAPI_PROXY_EXPORT FileIOResource
     28     : public PluginResource,
     29       public thunk::PPB_FileIO_API {
     30  public:
     31   FileIOResource(Connection connection, PP_Instance instance);
     32   virtual ~FileIOResource();
     33 
     34   // Resource overrides.
     35   virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() OVERRIDE;
     36 
     37   // PPB_FileIO_API implementation.
     38   virtual int32_t Open(PP_Resource file_ref,
     39                        int32_t open_flags,
     40                        scoped_refptr<TrackedCallback> callback) OVERRIDE;
     41   virtual int32_t Query(PP_FileInfo* info,
     42                         scoped_refptr<TrackedCallback> callback) OVERRIDE;
     43   virtual int32_t Touch(PP_Time last_access_time,
     44                         PP_Time last_modified_time,
     45                         scoped_refptr<TrackedCallback> callback) OVERRIDE;
     46   virtual int32_t Read(int64_t offset,
     47                        char* buffer,
     48                        int32_t bytes_to_read,
     49                        scoped_refptr<TrackedCallback> callback) OVERRIDE;
     50   virtual int32_t ReadToArray(int64_t offset,
     51                               int32_t max_read_length,
     52                               PP_ArrayOutput* array_output,
     53                               scoped_refptr<TrackedCallback> callback) OVERRIDE;
     54   virtual int32_t Write(int64_t offset,
     55                         const char* buffer,
     56                         int32_t bytes_to_write,
     57                         scoped_refptr<TrackedCallback> callback) OVERRIDE;
     58   virtual int32_t SetLength(int64_t length,
     59                             scoped_refptr<TrackedCallback> callback) OVERRIDE;
     60   virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE;
     61   virtual void Close() OVERRIDE;
     62   virtual int32_t RequestOSFileHandle(
     63       PP_FileHandle* handle,
     64       scoped_refptr<TrackedCallback> callback) OVERRIDE;
     65 
     66  private:
     67   // FileHandleHolder is used to guarantee that file operations will have a
     68   // valid FD to operate on, even if they're in a different thread.
     69   // If instead we just passed the raw FD, the FD could be closed before the
     70   // file operation has a chance to run. It could interact with an invalid FD,
     71   // or worse, the FD value could be reused if another file is opened quickly
     72   // (POSIX is required to provide the lowest available value when opening a
     73   // file). This could result in strange problems such as writing data to the
     74   // wrong file.
     75   //
     76   // Operations that run on a background thread should hold one of these to
     77   // ensure they have a valid file descriptor. The file handle is only closed
     78   // when the last reference to the FileHandleHolder is removed, so we are
     79   // guaranteed to operate on the correct file descriptor. It *is* still
     80   // possible that the FileIOResource will be destroyed and "Abort" callbacks
     81   // just before the operation does its task (e.g., Reading). In that case, we
     82   // might for example Read from a file even though the FileIO has been
     83   // destroyed and the plugin's callback got a PP_ERROR_ABORTED result. In the
     84   // case of a write, we could write some data to the file despite the plugin
     85   // receiving a PP_ERROR_ABORTED instead of a successful result.
     86   class FileHandleHolder : public base::RefCountedThreadSafe<FileHandleHolder> {
     87    public:
     88     explicit FileHandleHolder(PP_FileHandle file_handle_);
     89     PP_FileHandle raw_handle() {
     90       return raw_handle_;
     91     }
     92     static bool IsValid(
     93         const scoped_refptr<FileIOResource::FileHandleHolder>& handle);
     94    private:
     95     friend class base::RefCountedThreadSafe<FileHandleHolder>;
     96     ~FileHandleHolder();
     97     PP_FileHandle raw_handle_;
     98   };
     99 
    100   // Class to perform file query operations across multiple threads.
    101   class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
    102    public:
    103     explicit QueryOp(scoped_refptr<FileHandleHolder> file_handle);
    104 
    105     // Queries the file. Called on the file thread (non-blocking) or the plugin
    106     // thread (blocking). This should not be called when we hold the proxy lock.
    107     int32_t DoWork();
    108 
    109     const base::PlatformFileInfo& file_info() const { return file_info_; }
    110 
    111    private:
    112     friend class base::RefCountedThreadSafe<QueryOp>;
    113     ~QueryOp();
    114 
    115     scoped_refptr<FileHandleHolder> file_handle_;
    116     base::PlatformFileInfo file_info_;
    117   };
    118 
    119   // Class to perform file read operations across multiple threads.
    120   class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
    121    public:
    122     ReadOp(scoped_refptr<FileHandleHolder> file_handle,
    123            int64_t offset,
    124            int32_t bytes_to_read);
    125 
    126     // Reads the file. Called on the file thread (non-blocking) or the plugin
    127     // thread (blocking). This should not be called when we hold the proxy lock.
    128     int32_t DoWork();
    129 
    130     char* buffer() const { return buffer_.get(); }
    131 
    132    private:
    133     friend class base::RefCountedThreadSafe<ReadOp>;
    134     ~ReadOp();
    135 
    136     scoped_refptr<FileHandleHolder> file_handle_;
    137     int64_t offset_;
    138     int32_t bytes_to_read_;
    139     scoped_ptr<char[]> buffer_;
    140   };
    141 
    142   int32_t ReadValidated(int64_t offset,
    143                         int32_t bytes_to_read,
    144                         const PP_ArrayOutput& array_output,
    145                         scoped_refptr<TrackedCallback> callback);
    146 
    147   // Completion tasks for file operations that are done in the plugin.
    148   int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
    149                           PP_FileInfo* info,
    150                           int32_t result);
    151   int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
    152                          PP_ArrayOutput array_output,
    153                          int32_t result);
    154 
    155   // Reply message handlers for operations that are done in the host.
    156   void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback,
    157                                   const ResourceMessageReplyParams& params);
    158   void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback,
    159                                    const ResourceMessageReplyParams& params);
    160   void OnPluginMsgRequestOSFileHandleComplete(
    161       scoped_refptr<TrackedCallback> callback,
    162       PP_FileHandle* output_handle,
    163       const ResourceMessageReplyParams& params);
    164 
    165   scoped_refptr<FileHandleHolder> file_handle_;
    166   PP_FileSystemType file_system_type_;
    167   scoped_refptr<Resource> file_system_resource_;
    168   bool called_close_;
    169   FileIOStateManager state_manager_;
    170 
    171   scoped_refptr<Resource> file_ref_;
    172 
    173   DISALLOW_COPY_AND_ASSIGN(FileIOResource);
    174 };
    175 
    176 }  // namespace proxy
    177 }  // namespace ppapi
    178 
    179 #endif  // PPAPI_PROXY_FILE_IO_RESOURCE_H_
    180