- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / file_io_resource.h
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
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"
19
20 namespace ppapi {
21
22 class TrackedCallback;
23
24 namespace proxy {
25
26 class PPAPI_PROXY_EXPORT FileIOResource
27     : public PluginResource,
28       public thunk::PPB_FileIO_API {
29  public:
30   FileIOResource(Connection connection, PP_Instance instance);
31   virtual ~FileIOResource();
32
33   // Resource overrides.
34   virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() OVERRIDE;
35
36   // PPB_FileIO_API implementation.
37   virtual int32_t Open(PP_Resource file_ref,
38                        int32_t open_flags,
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,
46                        char* buffer,
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,
54                         const char* buffer,
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;
64
65  private:
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
73   // wrong file.
74   //
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> {
86    public:
87     explicit FileHandleHolder(PP_FileHandle file_handle_);
88     PP_FileHandle raw_handle() {
89       return raw_handle_;
90     }
91     static bool IsValid(
92         const scoped_refptr<FileIOResource::FileHandleHolder>& handle);
93    private:
94     friend class base::RefCountedThreadSafe<FileHandleHolder>;
95     ~FileHandleHolder();
96     PP_FileHandle raw_handle_;
97   };
98
99   // Class to perform file query operations across multiple threads.
100   class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
101    public:
102     explicit QueryOp(scoped_refptr<FileHandleHolder> file_handle);
103
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.
106     int32_t DoWork();
107
108     const base::PlatformFileInfo& file_info() const { return file_info_; }
109
110    private:
111     friend class base::RefCountedThreadSafe<QueryOp>;
112     ~QueryOp();
113
114     scoped_refptr<FileHandleHolder> file_handle_;
115     base::PlatformFileInfo file_info_;
116   };
117
118   // Class to perform file read operations across multiple threads.
119   class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
120    public:
121     ReadOp(scoped_refptr<FileHandleHolder> file_handle,
122            int64_t offset,
123            int32_t bytes_to_read);
124
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.
127     int32_t DoWork();
128
129     char* buffer() const { return buffer_.get(); }
130
131    private:
132     friend class base::RefCountedThreadSafe<ReadOp>;
133     ~ReadOp();
134
135     scoped_refptr<FileHandleHolder> file_handle_;
136     int64_t offset_;
137     int32_t bytes_to_read_;
138     scoped_ptr<char[]> buffer_;
139   };
140
141   int32_t ReadValidated(int64_t offset,
142                         int32_t bytes_to_read,
143                         const PP_ArrayOutput& array_output,
144                         scoped_refptr<TrackedCallback> callback);
145
146   // Completion tasks for file operations that are done in the plugin.
147   int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
148                           PP_FileInfo* info,
149                           int32_t result);
150   int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
151                          PP_ArrayOutput array_output,
152                          int32_t result);
153
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);
163
164   scoped_refptr<FileHandleHolder> file_handle_;
165   PP_FileSystemType file_system_type_;
166   FileIOStateManager state_manager_;
167
168   scoped_refptr<Resource> file_ref_;
169
170   DISALLOW_COPY_AND_ASSIGN(FileIOResource);
171 };
172
173 }  // namespace proxy
174 }  // namespace ppapi
175
176 #endif  // PPAPI_PROXY_FILE_IO_RESOURCE_H_