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