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