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