OLD | NEW |
---|---|
(Empty) | |
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 #include "ppapi/proxy/file_io_resource.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "ipc/ipc_message.h" | |
9 #include "ppapi/c/pp_errors.h" | |
10 #include "ppapi/proxy/ppapi_messages.h" | |
11 #include "ppapi/shared_impl/array_writer.h" | |
12 #include "ppapi/shared_impl/ppapi_globals.h" | |
13 #include "ppapi/shared_impl/resource_tracker.h" | |
14 #include "ppapi/thunk/ppb_file_ref_api.h" | |
15 | |
16 using ppapi::thunk::PPB_FileRef_API; | |
17 | |
18 namespace { | |
19 | |
20 // An adapter to let Read() share the same implementation with ReadToArray(). | |
21 void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) { | |
22 return user_data; | |
23 } | |
24 | |
25 } // namespace | |
26 | |
27 namespace ppapi { | |
28 namespace proxy { | |
29 | |
30 FileIOResource::FileIOResource(Connection connection, PP_Instance instance) | |
31 : PluginResource(connection, instance), | |
32 PPB_FileIO_Shared(), | |
33 num_pending_ops_(0), | |
34 pending_op_(OPERATION_NONE) { | |
35 SendCreate(RENDERER, PpapiHostMsg_FileIO_Create()); | |
36 } | |
37 | |
38 FileIOResource::~FileIOResource() { | |
39 } | |
40 | |
41 thunk::PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() { | |
42 return this; | |
43 } | |
44 | |
45 int32_t FileIOResource::Open(PP_Resource file_ref, | |
46 int32_t open_flags, | |
47 scoped_refptr<TrackedCallback> callback) { | |
48 temp_callback_ = callback; | |
49 return PPB_FileIO_Shared::DoOpen(file_ref, open_flags); | |
50 } | |
51 | |
52 int32_t FileIOResource::Query(PP_FileInfo* info, | |
53 scoped_refptr<TrackedCallback> callback) { | |
54 temp_callback_ = callback; | |
55 temp_info_ = info; | |
56 return DoQuery(); | |
57 } | |
58 | |
59 int32_t FileIOResource::Touch(PP_Time last_access_time, | |
60 PP_Time last_modified_time, | |
61 scoped_refptr<TrackedCallback> callback) { | |
62 temp_callback_ = callback; | |
63 return DoTouch(last_access_time, last_modified_time); | |
64 } | |
65 | |
66 int32_t FileIOResource::Read(int64_t offset, | |
67 char* buffer, | |
68 int32_t bytes_to_read, | |
69 scoped_refptr<TrackedCallback> callback) { | |
70 temp_callback_ = callback; | |
71 temp_array_output_.GetDataBuffer = &DummyGetDataBuffer; | |
72 temp_array_output_.user_data = buffer; | |
73 return PPB_FileIO_Shared::DoRead(offset, bytes_to_read); | |
74 } | |
75 | |
76 int32_t FileIOResource::ReadToArray(int64_t offset, | |
77 int32_t max_read_length, | |
78 PP_ArrayOutput* array_output, | |
79 scoped_refptr<TrackedCallback> callback) { | |
80 DCHECK(array_output); | |
81 temp_callback_ = callback; | |
82 temp_array_output_ = *array_output; | |
83 return PPB_FileIO_Shared::DoRead(offset, max_read_length); | |
84 } | |
85 | |
86 int32_t FileIOResource::Write(int64_t offset, | |
87 const char* buffer, | |
88 int32_t bytes_to_write, | |
89 scoped_refptr<TrackedCallback> callback) { | |
90 temp_callback_ = callback; | |
91 return PPB_FileIO_Shared::DoWrite(offset, buffer, bytes_to_write); | |
92 } | |
93 | |
94 int32_t FileIOResource::SetLength(int64_t length, | |
95 scoped_refptr<TrackedCallback> callback) { | |
96 temp_callback_ = callback; | |
97 return PPB_FileIO_Shared::DoSetLength(length); | |
98 } | |
99 | |
100 int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) { | |
101 temp_callback_ = callback; | |
102 return PPB_FileIO_Shared::DoFlush(); | |
103 } | |
104 | |
105 void FileIOResource::Close() { | |
106 Post(RENDERER, PpapiHostMsg_FileIO_Close()); | |
107 } | |
108 | |
109 int32_t FileIOResource::GetOSFileDescriptor() { | |
110 int32_t file_descriptor; | |
111 // Only available when runs in process. | |
112 SyncCall<PpapiPluginMsg_FileIO_GetOSFileDescriptorReply>( | |
113 RENDERER, PpapiHostMsg_FileIO_GetOSFileDescriptor(), &file_descriptor); | |
114 return file_descriptor; | |
115 } | |
116 | |
117 int32_t FileIOResource::WillWrite(int64_t offset, | |
118 int32_t bytes_to_write, | |
119 scoped_refptr<TrackedCallback> callback) { | |
120 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
121 PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write), | |
122 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
123 callback)); | |
124 SetOpInProgress(OPERATION_EXCLUSIVE); | |
125 return PP_OK_COMPLETIONPENDING; | |
126 } | |
127 | |
128 int32_t FileIOResource::WillSetLength(int64_t length, | |
129 scoped_refptr<TrackedCallback> callback) { | |
130 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
131 PpapiHostMsg_FileIO_WillSetLength(length), | |
132 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
133 callback)); | |
134 SetOpInProgress(OPERATION_EXCLUSIVE); | |
135 return PP_OK_COMPLETIONPENDING; | |
136 } | |
137 | |
138 int32_t FileIOResource::CommonPreCondition(bool should_be_open, | |
139 OperationType new_op) { | |
140 if (!CheckOpenState(should_be_open)) | |
141 return PP_ERROR_FAILED; | |
142 | |
143 if (pending_op_ != OPERATION_NONE && | |
144 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) | |
145 return PP_ERROR_INPROGRESS; | |
146 | |
147 return PP_OK; | |
148 } | |
149 | |
150 void FileIOResource::CommonPostCondition(OperationType new_op) { | |
151 SetOpInProgress(new_op); | |
152 } | |
153 | |
154 int32_t FileIOResource::OpenValidated(PP_Resource file_ref_resource, | |
155 PPB_FileRef_API* file_ref_api, | |
156 int32_t open_flags) { | |
157 Resource* file_ref_object = | |
158 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_resource); | |
raymes
2012/11/27 16:41:30
You can use EnterResourceNoLock here.
victorhsieh
2012/11/28 04:11:55
Done.
| |
159 | |
160 Call<PpapiPluginMsg_FileIO_OpenFileComplete>(RENDERER, | |
161 PpapiHostMsg_FileIO_Open( | |
162 file_ref_object->host_resource().host_resource(), | |
163 open_flags), | |
164 base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this, | |
165 temp_callback_)); | |
166 return PP_OK_COMPLETIONPENDING; | |
167 } | |
168 | |
169 int32_t FileIOResource::QueryValidated() { | |
170 Call<PpapiPluginMsg_FileIO_QueryComplete>(RENDERER, | |
171 PpapiHostMsg_FileIO_Query(), | |
172 base::Bind(&FileIOResource::OnPluginMsgQueryComplete, this, | |
173 temp_callback_, temp_info_)); | |
174 return PP_OK_COMPLETIONPENDING; | |
175 } | |
176 | |
177 int32_t FileIOResource::TouchValidated(PP_Time last_access_time, | |
178 PP_Time last_modified_time) { | |
179 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
180 PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time), | |
181 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
182 temp_callback_)); | |
183 return PP_OK_COMPLETIONPENDING; | |
184 } | |
185 | |
186 int32_t FileIOResource::ReadValidated(int64_t offset, | |
187 int32_t bytes_to_read) { | |
188 Call<PpapiPluginMsg_FileIO_ReadComplete>(RENDERER, | |
189 PpapiHostMsg_FileIO_Read(offset, bytes_to_read), | |
190 base::Bind(&FileIOResource::OnPluginMsgReadComplete, this, | |
191 temp_callback_, temp_array_output_)); | |
192 return PP_OK_COMPLETIONPENDING; | |
193 } | |
194 | |
195 int32_t FileIOResource::WriteValidated(int64_t offset, | |
196 const char* buffer, | |
197 int32_t bytes_to_write) { | |
198 // TODO(brettw) it would be nice to use a shared memory buffer for large | |
199 // writes rather than having to copy to a string (which will involve a number | |
200 // of extra copies to serialize over IPC). | |
201 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
202 PpapiHostMsg_FileIO_Write(offset, std::string(buffer, bytes_to_write)), | |
203 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
204 temp_callback_)); | |
205 return PP_OK_COMPLETIONPENDING; | |
206 } | |
207 | |
208 int32_t FileIOResource::SetLengthValidated(int64_t length) { | |
209 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
210 PpapiHostMsg_FileIO_SetLength(length), | |
211 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
212 temp_callback_)); | |
213 return PP_OK_COMPLETIONPENDING; | |
214 } | |
215 | |
216 int32_t FileIOResource::FlushValidated() { | |
217 Call<PpapiPluginMsg_FileIO_GeneralComplete>(RENDERER, | |
218 PpapiHostMsg_FileIO_Flush(), | |
219 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, | |
220 temp_callback_)); | |
221 return PP_OK_COMPLETIONPENDING; | |
222 } | |
223 | |
224 void FileIOResource::OnPluginMsgGeneralComplete( | |
225 scoped_refptr<TrackedCallback> callback, | |
226 const ResourceMessageReplyParams& params) { | |
227 DCHECK(pending_op_ == OPERATION_EXCLUSIVE || | |
228 pending_op_ == OPERATION_WRITE); | |
229 callback->Run(params.result()); | |
230 SetOpFinished(); | |
231 } | |
232 | |
233 void FileIOResource::OnPluginMsgOpenFileComplete( | |
234 scoped_refptr<TrackedCallback> callback, | |
235 const ResourceMessageReplyParams& params) { | |
236 DCHECK(pending_op_ == OPERATION_EXCLUSIVE); | |
237 if (params.result() == PP_OK) | |
238 SetOpenSucceed(); | |
239 callback->Run(params.result()); | |
240 SetOpFinished(); | |
241 } | |
242 | |
243 void FileIOResource::OnPluginMsgQueryComplete( | |
244 scoped_refptr<TrackedCallback> callback, | |
245 PP_FileInfo* output_info, | |
246 const ResourceMessageReplyParams& params, | |
247 const PP_FileInfo& info) { | |
248 DCHECK(pending_op_ == OPERATION_EXCLUSIVE); | |
249 *output_info = info; | |
250 callback->Run(params.result()); | |
251 SetOpFinished(); | |
252 } | |
253 | |
254 void FileIOResource::OnPluginMsgReadComplete( | |
255 scoped_refptr<TrackedCallback> callback, | |
256 PP_ArrayOutput array_output, | |
257 const ResourceMessageReplyParams& params, | |
258 const std::string& data) { | |
259 DCHECK(pending_op_ == OPERATION_READ); | |
260 | |
261 // The result code should contain the data size if it's positive. | |
262 int32_t result = params.result(); | |
263 DCHECK((result < 0 && data.size() == 0) || | |
264 result == static_cast<int32_t>(data.size())); | |
265 | |
266 ArrayWriter output; | |
267 output.set_pp_array_output(array_output); | |
268 if (output.is_valid()) | |
raymes
2012/11/27 16:41:30
If this fails, maybe we should run the callback wi
victorhsieh
2012/11/28 04:11:55
Done.
| |
269 output.StoreArray(data.data(), std::max(0, result)); | |
270 | |
271 callback->Run(result); | |
272 SetOpFinished(); | |
273 } | |
274 | |
275 void FileIOResource::SetOpInProgress(OperationType new_op) { | |
276 DCHECK(pending_op_ == OPERATION_NONE || | |
277 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == new_op)); | |
278 pending_op_ = new_op; | |
279 num_pending_ops_++; | |
280 } | |
281 | |
282 void FileIOResource::SetOpFinished() { | |
283 DCHECK(num_pending_ops_ > 0); | |
284 if (--num_pending_ops_ == 0) | |
285 pending_op_ = OPERATION_NONE; | |
286 } | |
287 | |
288 } // namespace proxy | |
289 } // namespace ppapi | |
OLD | NEW |