[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 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 | |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 10 | #include "base/memory/ref_counted.h" |
[email protected] | c6420f08 | 2013-09-18 22:42:41 | [diff] [blame] | 11 | #include "base/memory/scoped_ptr.h" |
[email protected] | 8f96cef | 2013-04-01 16:51:13 | [diff] [blame] | 12 | #include "ppapi/c/private/pp_file_handle.h" |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 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" |
[email protected] | c6420f08 | 2013-09-18 22:42:41 | [diff] [blame] | 17 | #include "ppapi/shared_impl/resource.h" |
[email protected] | 4837a98 | 2013-11-25 18:11:13 | [diff] [blame] | 18 | #include "ppapi/shared_impl/scoped_pp_resource.h" |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 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; |
[email protected] | 8f96cef | 2013-04-01 16:51:13 | [diff] [blame] | 62 | virtual int32_t RequestOSFileHandle( |
| 63 | PP_FileHandle* handle, |
| 64 | scoped_refptr<TrackedCallback> callback) OVERRIDE; |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 65 | |
| 66 | private: |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 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 | |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 100 | // Class to perform file query operations across multiple threads. |
| 101 | class QueryOp : public base::RefCountedThreadSafe<QueryOp> { |
| 102 | public: |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 103 | explicit QueryOp(scoped_refptr<FileHandleHolder> file_handle); |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 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 | |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 115 | scoped_refptr<FileHandleHolder> file_handle_; |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 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: |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 122 | ReadOp(scoped_refptr<FileHandleHolder> file_handle, |
| 123 | int64_t offset, |
| 124 | int32_t bytes_to_read); |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 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 | |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 136 | scoped_refptr<FileHandleHolder> file_handle_; |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 137 | int64_t offset_; |
| 138 | int32_t bytes_to_read_; |
| 139 | scoped_ptr<char[]> buffer_; |
| 140 | }; |
| 141 | |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 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 | |
[email protected] | 914a4ba9 | 2013-08-10 13:38:48 | [diff] [blame] | 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 | |
[email protected] | d45f29b | 2013-08-09 04:18:06 | [diff] [blame] | 155 | // Reply message handlers for operations that are done in the host. |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 156 | void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback, |
| 157 | const ResourceMessageReplyParams& params); |
| 158 | void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback, |
| 159 | const ResourceMessageReplyParams& params); |
[email protected] | 8f96cef | 2013-04-01 16:51:13 | [diff] [blame] | 160 | void OnPluginMsgRequestOSFileHandleComplete( |
| 161 | scoped_refptr<TrackedCallback> callback, |
| 162 | PP_FileHandle* output_handle, |
| 163 | const ResourceMessageReplyParams& params); |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 164 | |
[email protected] | d35d3f4 | 2013-10-02 19:52:20 | [diff] [blame] | 165 | scoped_refptr<FileHandleHolder> file_handle_; |
[email protected] | d45f29b | 2013-08-09 04:18:06 | [diff] [blame] | 166 | PP_FileSystemType file_system_type_; |
[email protected] | 4837a98 | 2013-11-25 18:11:13 | [diff] [blame] | 167 | ScopedPPResource file_system_resource_; |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 168 | FileIOStateManager state_manager_; |
| 169 | |
[email protected] | c6420f08 | 2013-09-18 22:42:41 | [diff] [blame] | 170 | scoped_refptr<Resource> file_ref_; |
| 171 | |
[email protected] | c7714472 | 2013-01-19 04:16:36 | [diff] [blame] | 172 | DISALLOW_COPY_AND_ASSIGN(FileIOResource); |
| 173 | }; |
| 174 | |
| 175 | } // namespace proxy |
| 176 | } // namespace ppapi |
| 177 | |
| 178 | #endif // PPAPI_PROXY_FILE_IO_RESOURCE_H_ |