Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: ppapi/proxy/ppb_file_io_proxy.cc

Issue 8764003: Implement a proxy for Pepper FileIO. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments addressed. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/ppb_file_io_proxy.h"
6
7 #include "ppapi/c/pp_errors.h"
8 #include "ppapi/proxy/enter_proxy.h"
9 #include "ppapi/proxy/ppapi_messages.h"
10 #include "ppapi/proxy/ppb_file_ref_proxy.h"
11 #include "ppapi/shared_impl/ppapi_globals.h"
12 #include "ppapi/shared_impl/resource.h"
13 #include "ppapi/shared_impl/resource_tracker.h"
14
15 using ppapi::thunk::PPB_FileIO_API;
16 using ppapi::thunk::PPB_FileRef_API;
17
18 namespace ppapi {
19 namespace proxy {
20
21 namespace {
22
23 // The maximum size we'll support reading in one chunk. The renderer process
24 // must allocate a buffer sized according to the request of the plugin. To
25 // keep things from getting out of control, we cap the read size to this value.
26 // This should generally be OK since the API specifies that it may perform a
27 // partial read.
28 static const int32_t kMaxReadSize = 33554432; // 32MB
29
30 typedef EnterHostFromHostResourceForceCallback<PPB_FileIO_API> EnterHostFileIO;
31 typedef EnterPluginFromHostResource<PPB_FileIO_API> EnterPluginFileIO;
32
33 class FileIO : public FileIOImpl {
34 public:
35 explicit FileIO(const HostResource& host_resource);
36 virtual ~FileIO();
37
38 // PPB_FileIO_API implementation (not provided by FileIOImpl).
39 virtual void Close() OVERRIDE;
40 virtual int32_t GetOSFileDescriptor() OVERRIDE;
41 virtual int32_t WillWrite(int64_t offset,
42 int32_t bytes_to_write,
43 PP_CompletionCallback callback) OVERRIDE;
44 virtual int32_t WillSetLength(int64_t length,
45 PP_CompletionCallback callback) OVERRIDE;
46
47 private:
48 // FileIOImpl overrides.
49 virtual int32_t OpenValidated(PP_Resource file_ref_resource,
50 PPB_FileRef_API* file_ref_api,
51 int32_t open_flags,
52 PP_CompletionCallback callback) OVERRIDE;
53 virtual int32_t QueryValidated(PP_FileInfo* info,
54 PP_CompletionCallback callback) OVERRIDE;
55 virtual int32_t TouchValidated(PP_Time last_access_time,
56 PP_Time last_modified_time,
57 PP_CompletionCallback callback) OVERRIDE;
58 virtual int32_t ReadValidated(int64_t offset,
59 char* buffer,
60 int32_t bytes_to_read,
61 PP_CompletionCallback callback) OVERRIDE;
62 virtual int32_t WriteValidated(int64_t offset,
63 const char* buffer,
64 int32_t bytes_to_write,
65 PP_CompletionCallback callback) OVERRIDE;
66 virtual int32_t SetLengthValidated(int64_t length,
67 PP_CompletionCallback callback) OVERRIDE;
68 virtual int32_t FlushValidated(PP_CompletionCallback callback) OVERRIDE;
69
70 PluginDispatcher* GetDispatcher() const {
71 return PluginDispatcher::GetForResource(this);
72 }
73
74 static const ApiID kApiID = API_ID_PPB_FILE_IO;
75
76 DISALLOW_IMPLICIT_CONSTRUCTORS(FileIO);
77 };
78
79 FileIO::FileIO(const HostResource& host_resource)
80 : FileIOImpl(host_resource) {
81 }
82
83 FileIO::~FileIO() {
84 Close();
85 }
86
87 void FileIO::Close() {
88 if (file_open_) {
89 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Close(kApiID,
90 host_resource()));
91 }
92 }
93
94 int32_t FileIO::GetOSFileDescriptor() {
95 return -1;
96 }
97
98 int32_t FileIO::WillWrite(int64_t offset,
99 int32_t bytes_to_write,
100 PP_CompletionCallback callback) {
101 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_WillWrite(
102 kApiID, host_resource(), offset, bytes_to_write));
103 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
104 return PP_OK_COMPLETIONPENDING;
105 }
106
107 int32_t FileIO::WillSetLength(int64_t length,
108 PP_CompletionCallback callback) {
109 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_WillSetLength(
110 kApiID, host_resource(), length));
111 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
112 return PP_OK_COMPLETIONPENDING;
113 }
114
115 int32_t FileIO::OpenValidated(PP_Resource file_ref_resource,
116 PPB_FileRef_API* file_ref_api,
117 int32_t open_flags,
118 PP_CompletionCallback callback) {
119 Resource* file_ref_object =
120 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_resource);
121
122 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Open(
123 kApiID, host_resource(), file_ref_object->host_resource(), open_flags));
124 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
125 return PP_OK_COMPLETIONPENDING;
126 }
127
128 int32_t FileIO::QueryValidated(PP_FileInfo* info,
129 PP_CompletionCallback callback) {
130 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Query(
131 kApiID, host_resource()));
132 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, info);
133 return PP_OK_COMPLETIONPENDING;
134 }
135
136 int32_t FileIO::TouchValidated(PP_Time last_access_time,
137 PP_Time last_modified_time,
138 PP_CompletionCallback callback) {
139 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Touch(
140 kApiID, host_resource(), last_access_time, last_modified_time));
141 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
142 return PP_OK_COMPLETIONPENDING;
143 }
144
145 int32_t FileIO::ReadValidated(int64_t offset,
146 char* buffer,
147 int32_t bytes_to_read,
148 PP_CompletionCallback callback) {
149 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Read(
150 kApiID, host_resource(), offset, bytes_to_read));
151 RegisterCallback(OPERATION_READ, callback, buffer, NULL);
152 return PP_OK_COMPLETIONPENDING;
153 }
154
155 int32_t FileIO::WriteValidated(int64_t offset,
156 const char* buffer,
157 int32_t bytes_to_write,
158 PP_CompletionCallback callback) {
159 // TODO(brettw) it would be nice to use a shared memory buffer for large
160 // writes rather than having to copy to a string (which will involve a number
161 // of extra copies to serialize over IPC).
162 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Write(
163 kApiID, host_resource(), offset, std::string(buffer, bytes_to_write)));
164 RegisterCallback(OPERATION_WRITE, callback, NULL, NULL);
165 return PP_OK_COMPLETIONPENDING;
166 }
167
168 int32_t FileIO::SetLengthValidated(int64_t length,
169 PP_CompletionCallback callback) {
170 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_SetLength(
171 kApiID, host_resource(), length));
172 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
173 return PP_OK_COMPLETIONPENDING;
174 }
175
176 int32_t FileIO::FlushValidated(PP_CompletionCallback callback) {
177 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Flush(
178 kApiID, host_resource()));
179 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
180 return PP_OK_COMPLETIONPENDING;
181 }
182
183 } // namespace
184
185 // -----------------------------------------------------------------------------
186
187 PPB_FileIO_Proxy::PPB_FileIO_Proxy(Dispatcher* dispatcher)
188 : InterfaceProxy(dispatcher),
189 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
190 }
191
192 PPB_FileIO_Proxy::~PPB_FileIO_Proxy() {
193 }
194
195 // static
196 PP_Resource PPB_FileIO_Proxy::CreateProxyResource(PP_Instance instance) {
197 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
198 if (!dispatcher)
199 return 0;
200
201 HostResource result;
202 dispatcher->Send(new PpapiHostMsg_PPBFileIO_Create(kApiID, instance,
203 &result));
204 if (result.is_null())
205 return 0;
206 return (new FileIO(result))->GetReference();
207 }
208
209 bool PPB_FileIO_Proxy::OnMessageReceived(const IPC::Message& msg) {
210 bool handled = true;
211 IPC_BEGIN_MESSAGE_MAP(PPB_FileIO_Proxy, msg)
212 // Plugin -> host message.
213 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Create, OnHostMsgCreate)
214 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Open, OnHostMsgOpen)
215 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Close, OnHostMsgClose)
216 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Query, OnHostMsgQuery)
217 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Touch, OnHostMsgTouch)
218 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Read, OnHostMsgRead)
219 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Write, OnHostMsgWrite)
220 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_SetLength, OnHostMsgSetLength)
221 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Flush, OnHostMsgFlush)
222 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_WillWrite, OnHostMsgWillWrite)
223 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_WillSetLength,
224 OnHostMsgWillSetLength)
225
226 // Host -> plugin messages.
227 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_GeneralComplete,
228 OnPluginMsgGeneralComplete)
229 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_OpenFileComplete,
230 OnPluginMsgOpenFileComplete)
231 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_QueryComplete,
232 OnPluginMsgQueryComplete)
233 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_ReadComplete,
234 OnPluginMsgReadComplete)
235 IPC_MESSAGE_UNHANDLED(handled = false)
236 IPC_END_MESSAGE_MAP()
237 return handled;
238 }
239
240 void PPB_FileIO_Proxy::OnHostMsgCreate(PP_Instance instance,
241 HostResource* result) {
242 thunk::EnterResourceCreation enter(instance);
243 if (enter.succeeded()) {
244 result->SetHostResource(instance,
245 enter.functions()->CreateFileIO(instance));
246 }
247 }
248
249 void PPB_FileIO_Proxy::OnHostMsgOpen(const HostResource& host_resource,
250 const HostResource& file_ref_resource,
251 int32_t open_flags) {
252 EnterHostFileIO enter(host_resource, callback_factory_,
253 &PPB_FileIO_Proxy::OpenFileCallbackCompleteInHost, host_resource);
254 if (enter.succeeded()) {
255 enter.SetResult(enter.object()->Open(
256 file_ref_resource.host_resource(), open_flags, enter.callback()));
257 }
258 }
259
260 void PPB_FileIO_Proxy::OnHostMsgClose(const HostResource& host_resource) {
261 EnterHostFromHostResource<PPB_FileIO_API> enter(host_resource);
262 if (enter.succeeded())
263 enter.object()->Close();
264 }
265
266 void PPB_FileIO_Proxy::OnHostMsgQuery(const HostResource& host_resource) {
267 // The callback will take charge of deleting the FileInfo. The contents must
268 // be defined so we don't send garbage to the plugin in the failure case.
269 PP_FileInfo* info = new PP_FileInfo;
270 memset(info, 0, sizeof(PP_FileInfo));
271 EnterHostFileIO enter(host_resource, callback_factory_,
272 &PPB_FileIO_Proxy::QueryCallbackCompleteInHost,
273 host_resource, info);
274 if (enter.succeeded())
275 enter.SetResult(enter.object()->Query(info, enter.callback()));
276 }
277
278 void PPB_FileIO_Proxy::OnHostMsgTouch(const HostResource& host_resource,
279 PP_Time last_access_time,
280 PP_Time last_modified_time) {
281 EnterHostFileIO enter(host_resource, callback_factory_,
282 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
283 host_resource);
284 if (enter.succeeded()) {
285 enter.SetResult(enter.object()->Touch(last_access_time, last_modified_time,
286 enter.callback()));
287 }
288 }
289
290 void PPB_FileIO_Proxy::OnHostMsgRead(const HostResource& host_resource,
291 int64_t offset,
292 int32_t bytes_to_read) {
293 // Validate bytes_to_read before allocating below. This value is coming from
294 // the untrusted plugin.
295 bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
296 if (bytes_to_read < 0) {
297 ReadCallbackCompleteInHost(PP_ERROR_FAILED, host_resource,
298 new std::string());
299 return;
300 }
301
302 // The callback will take charge of deleting the string.
303 std::string* dest = new std::string;
304 dest->resize(bytes_to_read);
305 EnterHostFileIO enter(host_resource, callback_factory_,
306 &PPB_FileIO_Proxy::ReadCallbackCompleteInHost,
307 host_resource, dest);
308 if (enter.succeeded()) {
309 enter.SetResult(enter.object()->Read(offset,
310 bytes_to_read > 0 ? &(*dest)[0] : NULL,
311 bytes_to_read, enter.callback()));
312 }
313 }
314
315 void PPB_FileIO_Proxy::OnHostMsgWrite(const HostResource& host_resource,
316 int64_t offset,
317 const std::string& data) {
318 EnterHostFileIO enter(host_resource, callback_factory_,
319 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
320 host_resource);
321 if (enter.succeeded()) {
322 enter.SetResult(enter.object()->Write(offset, data.data(), data.size(),
323 enter.callback()));
324 }
325 }
326
327 void PPB_FileIO_Proxy::OnHostMsgSetLength(const HostResource& host_resource,
328 int64_t length) {
329 EnterHostFileIO enter(host_resource, callback_factory_,
330 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
331 host_resource);
332 if (enter.succeeded())
333 enter.SetResult(enter.object()->SetLength(length, enter.callback()));
334 }
335
336 void PPB_FileIO_Proxy::OnHostMsgFlush(const HostResource& host_resource) {
337 EnterHostFileIO enter(host_resource, callback_factory_,
338 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
339 host_resource);
340 if (enter.succeeded())
341 enter.SetResult(enter.object()->Flush(enter.callback()));
342 }
343
344 void PPB_FileIO_Proxy::OnHostMsgWillWrite(const HostResource& host_resource,
345 int64_t offset,
346 int32_t bytes_to_write) {
347 EnterHostFileIO enter(host_resource, callback_factory_,
348 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
349 host_resource);
350 if (enter.succeeded()) {
351 enter.SetResult(enter.object()->WillWrite(offset, bytes_to_write,
352 enter.callback()));
353 }
354 }
355
356 void PPB_FileIO_Proxy::OnHostMsgWillSetLength(const HostResource& host_resource,
357 int64_t length) {
358 EnterHostFileIO enter(host_resource, callback_factory_,
359 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
360 host_resource);
361 if (enter.succeeded())
362 enter.SetResult(enter.object()->WillSetLength(length, enter.callback()));
363 }
364
365 void PPB_FileIO_Proxy::OnPluginMsgGeneralComplete(
366 const HostResource& host_resource,
367 int32_t result) {
368 EnterPluginFileIO enter(host_resource);
369 if (enter.succeeded())
370 static_cast<FileIO*>(enter.object())->ExecuteGeneralCallback(result);
371 }
372
373 void PPB_FileIO_Proxy::OnPluginMsgOpenFileComplete(
374 const HostResource& host_resource,
375 int32_t result) {
376 EnterPluginFileIO enter(host_resource);
377 if (enter.succeeded())
378 static_cast<FileIO*>(enter.object())->ExecuteOpenFileCallback(result);
379 }
380
381 void PPB_FileIO_Proxy::OnPluginMsgQueryComplete(
382 const HostResource& host_resource,
383 int32_t result,
384 const PP_FileInfo& info) {
385 EnterPluginFileIO enter(host_resource);
386 if (enter.succeeded())
387 static_cast<FileIO*>(enter.object())->ExecuteQueryCallback(result, info);
388 }
389
390 void PPB_FileIO_Proxy::OnPluginMsgReadComplete(
391 const HostResource& host_resource,
392 int32_t result,
393 const std::string& data) {
394 EnterPluginFileIO enter(host_resource);
395 if (enter.succeeded()) {
396 // The result code should contain the data size if it's positive.
397 DCHECK((result < 0 && data.size() == 0) ||
398 result == static_cast<int32_t>(data.size()));
399 static_cast<FileIO*>(enter.object())->ExecuteReadCallback(result,
400 data.data());
401 }
402 }
403
404 void PPB_FileIO_Proxy::GeneralCallbackCompleteInHost(
405 int32_t pp_error,
406 const HostResource& host_resource) {
407 Send(new PpapiMsg_PPBFileIO_GeneralComplete(kApiID, host_resource, pp_error));
408 }
409
410 void PPB_FileIO_Proxy::OpenFileCallbackCompleteInHost(
411 int32_t pp_error,
412 const HostResource& host_resource) {
413 Send(new PpapiMsg_PPBFileIO_OpenFileComplete(kApiID, host_resource,
414 pp_error));
415 }
416
417 void PPB_FileIO_Proxy::QueryCallbackCompleteInHost(
418 int32_t pp_error,
419 const HostResource& host_resource,
420 PP_FileInfo* info) {
421 Send(new PpapiMsg_PPBFileIO_QueryComplete(kApiID, host_resource, pp_error,
422 *info));
423 delete info;
424 }
425
426 void PPB_FileIO_Proxy::ReadCallbackCompleteInHost(
427 int32_t pp_error,
428 const HostResource& host_resource,
429 std::string* data) {
430 // Only send the amount of data in the string that was actually read.
431 if (pp_error >= 0) {
432 DCHECK(pp_error <= static_cast<int32_t>(data->size()));
433 data->resize(pp_error);
434 }
435 Send(new PpapiMsg_PPBFileIO_ReadComplete(kApiID, host_resource, pp_error,
436 *data));
437 delete data;
438 }
439
440 } // namespace proxy
441 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698