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.
5 #ifndef PPAPI_PROXY_FILE_IO_RESOURCE_H_
6 #define PPAPI_PROXY_FILE_IO_RESOURCE_H_
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"
24 class TrackedCallback
;
28 class PPAPI_PROXY_EXPORT FileIOResource
29 : public PluginResource
,
30 public thunk::PPB_FileIO_API
{
32 FileIOResource(Connection connection
, PP_Instance instance
);
33 virtual ~FileIOResource();
35 // Resource overrides.
36 virtual thunk::PPB_FileIO_API
* AsPPB_FileIO_API() override
;
38 // PPB_FileIO_API implementation.
39 virtual int32_t Open(PP_Resource file_ref
,
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
,
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
,
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
;
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
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
> {
93 explicit FileHolder(PP_FileHandle file_handle
);
98 const scoped_refptr
<FileIOResource::FileHolder
>& handle
);
100 friend class base::RefCountedThreadSafe
<FileHolder
>;
105 scoped_refptr
<FileHolder
> file_holder() {
110 // Class to perform file query operations across multiple threads.
111 class QueryOp
: public base::RefCountedThreadSafe
<QueryOp
> {
113 explicit QueryOp(scoped_refptr
<FileHolder
> file_holder
);
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.
119 const base::File::Info
& file_info() const { return file_info_
; }
122 friend class base::RefCountedThreadSafe
<QueryOp
>;
125 scoped_refptr
<FileHolder
> file_holder_
;
126 base::File::Info file_info_
;
129 // Class to perform file read operations across multiple threads.
130 class ReadOp
: public base::RefCountedThreadSafe
<ReadOp
> {
132 ReadOp(scoped_refptr
<FileHolder
> file_holder
,
134 int32_t bytes_to_read
);
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.
140 char* buffer() const { return buffer_
.get(); }
143 friend class base::RefCountedThreadSafe
<ReadOp
>;
146 scoped_refptr
<FileHolder
> file_holder_
;
148 int32_t bytes_to_read_
;
149 scoped_ptr
<char[]> buffer_
;
152 // Class to perform file write operations across multiple threads.
153 class WriteOp
: public base::RefCountedThreadSafe
<WriteOp
> {
155 WriteOp(scoped_refptr
<FileHolder
> file_holder
,
157 scoped_ptr
<char[]> buffer
,
158 int32_t bytes_to_write
,
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.
166 friend class base::RefCountedThreadSafe
<WriteOp
>;
169 scoped_refptr
<FileHolder
> file_holder_
;
171 scoped_ptr
<char[]> buffer_
;
172 int32_t bytes_to_write_
;
176 void OnRequestWriteQuotaComplete(int64_t offset
,
177 scoped_ptr
<char[]> buffer
,
178 int32_t bytes_to_write
,
179 scoped_refptr
<TrackedCallback
> callback
,
181 void OnRequestSetLengthQuotaComplete(int64_t length
,
182 scoped_refptr
<TrackedCallback
> callback
,
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
,
191 int32_t bytes_to_write
,
192 scoped_refptr
<TrackedCallback
> callback
);
193 void SetLengthValidated(int64_t length
,
194 scoped_refptr
<TrackedCallback
> callback
);
196 // Completion tasks for file operations that are done in the plugin.
197 int32_t OnQueryComplete(scoped_refptr
<QueryOp
> query_op
,
200 int32_t OnReadComplete(scoped_refptr
<ReadOp
> read_op
,
201 PP_ArrayOutput array_output
,
203 int32_t OnWriteComplete(int32_t result
);
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
);
217 scoped_refptr
<FileHolder
> file_holder_
;
218 PP_FileSystemType file_system_type_
;
219 scoped_refptr
<Resource
> file_system_resource_
;
220 FileIOStateManager state_manager_
;
222 scoped_refptr
<Resource
> file_ref_
;
225 int64_t max_written_offset_
;
226 int64_t append_mode_write_amount_
;
230 DISALLOW_COPY_AND_ASSIGN(FileIOResource
);
236 #endif // PPAPI_PROXY_FILE_IO_RESOURCE_H_