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/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/thunk/ppb_file_io_api.h"
22 class TrackedCallback;
26 class PPAPI_PROXY_EXPORT FileIOResource
27 : public PluginResource,
28 public thunk::PPB_FileIO_API {
30 FileIOResource(Connection connection, PP_Instance instance);
31 virtual ~FileIOResource();
33 // Resource overrides.
34 virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() OVERRIDE;
36 // PPB_FileIO_API implementation.
37 virtual int32_t Open(PP_Resource file_ref,
39 scoped_refptr<TrackedCallback> callback) OVERRIDE;
40 virtual int32_t Query(PP_FileInfo* info,
41 scoped_refptr<TrackedCallback> callback) OVERRIDE;
42 virtual int32_t Touch(PP_Time last_access_time,
43 PP_Time last_modified_time,
44 scoped_refptr<TrackedCallback> callback) OVERRIDE;
45 virtual int32_t Read(int64_t offset,
47 int32_t bytes_to_read,
48 scoped_refptr<TrackedCallback> callback) OVERRIDE;
49 virtual int32_t ReadToArray(int64_t offset,
50 int32_t max_read_length,
51 PP_ArrayOutput* array_output,
52 scoped_refptr<TrackedCallback> callback) OVERRIDE;
53 virtual int32_t Write(int64_t offset,
55 int32_t bytes_to_write,
56 scoped_refptr<TrackedCallback> callback) OVERRIDE;
57 virtual int32_t SetLength(int64_t length,
58 scoped_refptr<TrackedCallback> callback) OVERRIDE;
59 virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) OVERRIDE;
60 virtual void Close() OVERRIDE;
61 virtual int32_t RequestOSFileHandle(
62 PP_FileHandle* handle,
63 scoped_refptr<TrackedCallback> callback) OVERRIDE;
66 // FileHandleHolder is used to guarantee that file operations will have a
67 // valid FD to operate on, even if they're in a different thread.
68 // If instead we just passed the raw FD, the FD could be closed before the
69 // file operation has a chance to run. It could interact with an invalid FD,
70 // or worse, the FD value could be reused if another file is opened quickly
71 // (POSIX is required to provide the lowest available value when opening a
72 // file). This could result in strange problems such as writing data to the
75 // Operations that run on a background thread should hold one of these to
76 // ensure they have a valid file descriptor. The file handle is only closed
77 // when the last reference to the FileHandleHolder is removed, so we are
78 // guaranteed to operate on the correct file descriptor. It *is* still
79 // possible that the FileIOResource will be destroyed and "Abort" callbacks
80 // just before the operation does its task (e.g., Reading). In that case, we
81 // might for example Read from a file even though the FileIO has been
82 // destroyed and the plugin's callback got a PP_ERROR_ABORTED result. In the
83 // case of a write, we could write some data to the file despite the plugin
84 // receiving a PP_ERROR_ABORTED instead of a successful result.
85 class FileHandleHolder : public base::RefCountedThreadSafe<FileHandleHolder> {
87 explicit FileHandleHolder(PP_FileHandle file_handle_);
88 PP_FileHandle raw_handle() {
92 const scoped_refptr<FileIOResource::FileHandleHolder>& handle);
94 friend class base::RefCountedThreadSafe<FileHandleHolder>;
96 PP_FileHandle raw_handle_;
99 // Class to perform file query operations across multiple threads.
100 class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
102 explicit QueryOp(scoped_refptr<FileHandleHolder> file_handle);
104 // Queries the file. Called on the file thread (non-blocking) or the plugin
105 // thread (blocking). This should not be called when we hold the proxy lock.
108 const base::PlatformFileInfo& file_info() const { return file_info_; }
111 friend class base::RefCountedThreadSafe<QueryOp>;
114 scoped_refptr<FileHandleHolder> file_handle_;
115 base::PlatformFileInfo file_info_;
118 // Class to perform file read operations across multiple threads.
119 class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
121 ReadOp(scoped_refptr<FileHandleHolder> file_handle,
123 int32_t bytes_to_read);
125 // Reads the file. Called on the file thread (non-blocking) or the plugin
126 // thread (blocking). This should not be called when we hold the proxy lock.
129 char* buffer() const { return buffer_.get(); }
132 friend class base::RefCountedThreadSafe<ReadOp>;
135 scoped_refptr<FileHandleHolder> file_handle_;
137 int32_t bytes_to_read_;
138 scoped_ptr<char[]> buffer_;
141 int32_t ReadValidated(int64_t offset,
142 int32_t bytes_to_read,
143 const PP_ArrayOutput& array_output,
144 scoped_refptr<TrackedCallback> callback);
146 // Completion tasks for file operations that are done in the plugin.
147 int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
150 int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
151 PP_ArrayOutput array_output,
154 // Reply message handlers for operations that are done in the host.
155 void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback,
156 const ResourceMessageReplyParams& params);
157 void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback,
158 const ResourceMessageReplyParams& params);
159 void OnPluginMsgRequestOSFileHandleComplete(
160 scoped_refptr<TrackedCallback> callback,
161 PP_FileHandle* output_handle,
162 const ResourceMessageReplyParams& params);
164 scoped_refptr<FileHandleHolder> file_handle_;
165 PP_FileSystemType file_system_type_;
166 FileIOStateManager state_manager_;
168 scoped_refptr<Resource> file_ref_;
170 DISALLOW_COPY_AND_ASSIGN(FileIOResource);
176 #endif // PPAPI_PROXY_FILE_IO_RESOURCE_H_