Refactor android test results logging.
[chromium-blink-merge.git] / ppapi / proxy / ppb_file_io_proxy.cc
blob002efdf75e0a90e02c9029eb57ffce67d7a7dcb3
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.
5 #include "ppapi/proxy/ppb_file_io_proxy.h"
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/ppb_file_io_shared.h"
13 #include "ppapi/shared_impl/resource.h"
14 #include "ppapi/shared_impl/resource_tracker.h"
16 using ppapi::thunk::PPB_FileIO_API;
17 using ppapi::thunk::PPB_FileRef_API;
19 namespace ppapi {
20 namespace proxy {
22 namespace {
24 // The maximum size we'll support reading in one chunk. The renderer process
25 // must allocate a buffer sized according to the request of the plugin. To
26 // keep things from getting out of control, we cap the read size to this value.
27 // This should generally be OK since the API specifies that it may perform a
28 // partial read.
29 static const int32_t kMaxReadSize = 33554432; // 32MB
31 #if !defined(OS_NACL)
32 typedef EnterHostFromHostResourceForceCallback<PPB_FileIO_API> EnterHostFileIO;
33 #endif
34 typedef EnterPluginFromHostResource<PPB_FileIO_API> EnterPluginFileIO;
36 class FileIO : public PPB_FileIO_Shared {
37 public:
38 explicit FileIO(const HostResource& host_resource);
39 virtual ~FileIO();
41 // PPB_FileIO_API implementation (not provided by FileIOImpl).
42 virtual void Close() OVERRIDE;
43 virtual int32_t GetOSFileDescriptor() OVERRIDE;
44 virtual int32_t WillWrite(int64_t offset,
45 int32_t bytes_to_write,
46 scoped_refptr<TrackedCallback> callback) OVERRIDE;
47 virtual int32_t WillSetLength(
48 int64_t length,
49 scoped_refptr<TrackedCallback> callback) OVERRIDE;
51 private:
52 // FileIOImpl overrides.
53 virtual int32_t OpenValidated(
54 PP_Resource file_ref_resource,
55 PPB_FileRef_API* file_ref_api,
56 int32_t open_flags,
57 scoped_refptr<TrackedCallback> callback) OVERRIDE;
58 virtual int32_t QueryValidated(
59 PP_FileInfo* info,
60 scoped_refptr<TrackedCallback> callback) OVERRIDE;
61 virtual int32_t TouchValidated(
62 PP_Time last_access_time,
63 PP_Time last_modified_time,
64 scoped_refptr<TrackedCallback> callback) OVERRIDE;
65 virtual int32_t ReadValidated(
66 int64_t offset,
67 const PP_ArrayOutput& output_array_buffer,
68 int32_t max_read_length,
69 scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
70 virtual int32_t WriteValidated(
71 int64_t offset,
72 const char* buffer,
73 int32_t bytes_to_write,
74 scoped_refptr<TrackedCallback> callback) OVERRIDE;
75 virtual int32_t SetLengthValidated(
76 int64_t length,
77 scoped_refptr<TrackedCallback> callback) OVERRIDE;
78 virtual int32_t FlushValidated(
79 scoped_refptr<TrackedCallback> callback) OVERRIDE;
81 PluginDispatcher* GetDispatcher() const {
82 return PluginDispatcher::GetForResource(this);
85 static const ApiID kApiID = API_ID_PPB_FILE_IO;
87 DISALLOW_IMPLICIT_CONSTRUCTORS(FileIO);
90 FileIO::FileIO(const HostResource& host_resource)
91 : PPB_FileIO_Shared(host_resource) {
94 FileIO::~FileIO() {
95 Close();
98 void FileIO::Close() {
99 if (file_open_) {
100 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Close(kApiID,
101 host_resource()));
105 int32_t FileIO::GetOSFileDescriptor() {
106 return -1;
109 int32_t FileIO::WillWrite(int64_t offset,
110 int32_t bytes_to_write,
111 scoped_refptr<TrackedCallback> callback) {
112 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_WillWrite(
113 kApiID, host_resource(), offset, bytes_to_write));
114 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
115 return PP_OK_COMPLETIONPENDING;
118 int32_t FileIO::WillSetLength(int64_t length,
119 scoped_refptr<TrackedCallback> callback) {
120 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_WillSetLength(
121 kApiID, host_resource(), length));
122 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
123 return PP_OK_COMPLETIONPENDING;
126 int32_t FileIO::OpenValidated(PP_Resource file_ref_resource,
127 PPB_FileRef_API* file_ref_api,
128 int32_t open_flags,
129 scoped_refptr<TrackedCallback> callback) {
130 Resource* file_ref_object =
131 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_resource);
133 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Open(
134 kApiID, host_resource(), file_ref_object->host_resource(), open_flags));
135 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
136 return PP_OK_COMPLETIONPENDING;
139 int32_t FileIO::QueryValidated(PP_FileInfo* info,
140 scoped_refptr<TrackedCallback> callback) {
141 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Query(
142 kApiID, host_resource()));
143 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, info);
144 return PP_OK_COMPLETIONPENDING;
147 int32_t FileIO::TouchValidated(PP_Time last_access_time,
148 PP_Time last_modified_time,
149 scoped_refptr<TrackedCallback> callback) {
150 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Touch(
151 kApiID, host_resource(), last_access_time, last_modified_time));
152 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
153 return PP_OK_COMPLETIONPENDING;
156 int32_t FileIO::ReadValidated(int64_t offset,
157 const PP_ArrayOutput& output_array_buffer,
158 int32_t max_read_length,
159 scoped_refptr<TrackedCallback> callback) {
160 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Read(
161 kApiID, host_resource(), offset, max_read_length));
162 RegisterCallback(OPERATION_READ, callback, &output_array_buffer, NULL);
163 return PP_OK_COMPLETIONPENDING;
166 int32_t FileIO::WriteValidated(int64_t offset,
167 const char* buffer,
168 int32_t bytes_to_write,
169 scoped_refptr<TrackedCallback> callback) {
170 // TODO(brettw) it would be nice to use a shared memory buffer for large
171 // writes rather than having to copy to a string (which will involve a number
172 // of extra copies to serialize over IPC).
173 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Write(
174 kApiID, host_resource(), offset, std::string(buffer, bytes_to_write)));
175 RegisterCallback(OPERATION_WRITE, callback, NULL, NULL);
176 return PP_OK_COMPLETIONPENDING;
179 int32_t FileIO::SetLengthValidated(int64_t length,
180 scoped_refptr<TrackedCallback> callback) {
181 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_SetLength(
182 kApiID, host_resource(), length));
183 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
184 return PP_OK_COMPLETIONPENDING;
187 int32_t FileIO::FlushValidated(scoped_refptr<TrackedCallback> callback) {
188 GetDispatcher()->Send(new PpapiHostMsg_PPBFileIO_Flush(
189 kApiID, host_resource()));
190 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL, NULL);
191 return PP_OK_COMPLETIONPENDING;
194 } // namespace
196 // -----------------------------------------------------------------------------
198 PPB_FileIO_Proxy::PPB_FileIO_Proxy(Dispatcher* dispatcher)
199 : InterfaceProxy(dispatcher),
200 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
203 PPB_FileIO_Proxy::~PPB_FileIO_Proxy() {
206 // static
207 PP_Resource PPB_FileIO_Proxy::CreateProxyResource(PP_Instance instance) {
208 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
209 if (!dispatcher)
210 return 0;
212 HostResource result;
213 dispatcher->Send(new PpapiHostMsg_PPBFileIO_Create(kApiID, instance,
214 &result));
215 if (result.is_null())
216 return 0;
217 return (new FileIO(result))->GetReference();
220 bool PPB_FileIO_Proxy::OnMessageReceived(const IPC::Message& msg) {
221 bool handled = true;
222 IPC_BEGIN_MESSAGE_MAP(PPB_FileIO_Proxy, msg)
223 #if !defined(OS_NACL)
224 // Plugin -> host message.
225 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Create, OnHostMsgCreate)
226 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Open, OnHostMsgOpen)
227 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Close, OnHostMsgClose)
228 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Query, OnHostMsgQuery)
229 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Touch, OnHostMsgTouch)
230 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Read, OnHostMsgRead)
231 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Write, OnHostMsgWrite)
232 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_SetLength, OnHostMsgSetLength)
233 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_Flush, OnHostMsgFlush)
234 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_WillWrite, OnHostMsgWillWrite)
235 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileIO_WillSetLength,
236 OnHostMsgWillSetLength)
237 #endif // !defined(OS_NACL)
238 // Host -> plugin messages.
239 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_GeneralComplete,
240 OnPluginMsgGeneralComplete)
241 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_OpenFileComplete,
242 OnPluginMsgOpenFileComplete)
243 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_QueryComplete,
244 OnPluginMsgQueryComplete)
245 IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileIO_ReadComplete,
246 OnPluginMsgReadComplete)
247 IPC_MESSAGE_UNHANDLED(handled = false)
248 IPC_END_MESSAGE_MAP()
249 return handled;
252 #if !defined(OS_NACL)
253 void PPB_FileIO_Proxy::OnHostMsgCreate(PP_Instance instance,
254 HostResource* result) {
255 thunk::EnterResourceCreation enter(instance);
256 if (enter.succeeded()) {
257 result->SetHostResource(instance,
258 enter.functions()->CreateFileIO(instance));
262 void PPB_FileIO_Proxy::OnHostMsgOpen(const HostResource& host_resource,
263 const HostResource& file_ref_resource,
264 int32_t open_flags) {
265 EnterHostFileIO enter(host_resource, callback_factory_,
266 &PPB_FileIO_Proxy::OpenFileCallbackCompleteInHost, host_resource);
267 if (enter.succeeded()) {
268 enter.SetResult(enter.object()->Open(
269 file_ref_resource.host_resource(), open_flags, enter.callback()));
273 void PPB_FileIO_Proxy::OnHostMsgClose(const HostResource& host_resource) {
274 EnterHostFromHostResource<PPB_FileIO_API> enter(host_resource);
275 if (enter.succeeded())
276 enter.object()->Close();
279 void PPB_FileIO_Proxy::OnHostMsgQuery(const HostResource& host_resource) {
280 // The callback will take charge of deleting the FileInfo. The contents must
281 // be defined so we don't send garbage to the plugin in the failure case.
282 PP_FileInfo* info = new PP_FileInfo;
283 memset(info, 0, sizeof(PP_FileInfo));
284 EnterHostFileIO enter(host_resource, callback_factory_,
285 &PPB_FileIO_Proxy::QueryCallbackCompleteInHost,
286 host_resource, info);
287 if (enter.succeeded())
288 enter.SetResult(enter.object()->Query(info, enter.callback()));
291 void PPB_FileIO_Proxy::OnHostMsgTouch(const HostResource& host_resource,
292 PP_Time last_access_time,
293 PP_Time last_modified_time) {
294 EnterHostFileIO enter(host_resource, callback_factory_,
295 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
296 host_resource);
297 if (enter.succeeded()) {
298 enter.SetResult(enter.object()->Touch(last_access_time, last_modified_time,
299 enter.callback()));
303 void PPB_FileIO_Proxy::OnHostMsgRead(const HostResource& host_resource,
304 int64_t offset,
305 int32_t bytes_to_read) {
306 // Validate bytes_to_read before allocating below. This value is coming from
307 // the untrusted plugin.
308 bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
309 if (bytes_to_read < 0) {
310 ReadCallbackCompleteInHost(PP_ERROR_FAILED, host_resource,
311 new std::string());
312 return;
315 // The callback will take charge of deleting the string.
316 std::string* dest = new std::string;
317 dest->resize(bytes_to_read);
318 EnterHostFileIO enter(host_resource, callback_factory_,
319 &PPB_FileIO_Proxy::ReadCallbackCompleteInHost,
320 host_resource, dest);
321 if (enter.succeeded()) {
322 enter.SetResult(enter.object()->Read(offset,
323 bytes_to_read > 0 ? &(*dest)[0] : NULL,
324 bytes_to_read, enter.callback()));
328 void PPB_FileIO_Proxy::OnHostMsgWrite(const HostResource& host_resource,
329 int64_t offset,
330 const std::string& data) {
331 EnterHostFileIO enter(host_resource, callback_factory_,
332 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
333 host_resource);
334 if (enter.succeeded()) {
335 enter.SetResult(enter.object()->Write(offset, data.data(), data.size(),
336 enter.callback()));
340 void PPB_FileIO_Proxy::OnHostMsgSetLength(const HostResource& host_resource,
341 int64_t length) {
342 EnterHostFileIO enter(host_resource, callback_factory_,
343 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
344 host_resource);
345 if (enter.succeeded())
346 enter.SetResult(enter.object()->SetLength(length, enter.callback()));
349 void PPB_FileIO_Proxy::OnHostMsgFlush(const HostResource& host_resource) {
350 EnterHostFileIO enter(host_resource, callback_factory_,
351 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
352 host_resource);
353 if (enter.succeeded())
354 enter.SetResult(enter.object()->Flush(enter.callback()));
357 void PPB_FileIO_Proxy::OnHostMsgWillWrite(const HostResource& host_resource,
358 int64_t offset,
359 int32_t bytes_to_write) {
360 EnterHostFileIO enter(host_resource, callback_factory_,
361 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
362 host_resource);
363 if (enter.succeeded()) {
364 enter.SetResult(enter.object()->WillWrite(offset, bytes_to_write,
365 enter.callback()));
369 void PPB_FileIO_Proxy::OnHostMsgWillSetLength(const HostResource& host_resource,
370 int64_t length) {
371 EnterHostFileIO enter(host_resource, callback_factory_,
372 &PPB_FileIO_Proxy::GeneralCallbackCompleteInHost,
373 host_resource);
374 if (enter.succeeded())
375 enter.SetResult(enter.object()->WillSetLength(length, enter.callback()));
377 #endif // !defined(OS_NACL)
379 void PPB_FileIO_Proxy::OnPluginMsgGeneralComplete(
380 const HostResource& host_resource,
381 int32_t result) {
382 EnterPluginFileIO enter(host_resource);
383 if (enter.succeeded())
384 static_cast<FileIO*>(enter.object())->ExecuteGeneralCallback(result);
387 void PPB_FileIO_Proxy::OnPluginMsgOpenFileComplete(
388 const HostResource& host_resource,
389 int32_t result) {
390 EnterPluginFileIO enter(host_resource);
391 if (enter.succeeded())
392 static_cast<FileIO*>(enter.object())->ExecuteOpenFileCallback(result);
395 void PPB_FileIO_Proxy::OnPluginMsgQueryComplete(
396 const HostResource& host_resource,
397 int32_t result,
398 const PP_FileInfo& info) {
399 EnterPluginFileIO enter(host_resource);
400 if (enter.succeeded())
401 static_cast<FileIO*>(enter.object())->ExecuteQueryCallback(result, info);
404 void PPB_FileIO_Proxy::OnPluginMsgReadComplete(
405 const HostResource& host_resource,
406 int32_t result,
407 const std::string& data) {
408 EnterPluginFileIO enter(host_resource);
409 if (enter.succeeded()) {
410 // The result code should contain the data size if it's positive.
411 DCHECK((result < 0 && data.size() == 0) ||
412 result == static_cast<int32_t>(data.size()));
413 static_cast<FileIO*>(enter.object())->ExecuteReadCallback(result,
414 data.data());
418 #if !defined(OS_NACL)
419 void PPB_FileIO_Proxy::GeneralCallbackCompleteInHost(
420 int32_t pp_error,
421 const HostResource& host_resource) {
422 Send(new PpapiMsg_PPBFileIO_GeneralComplete(kApiID, host_resource, pp_error));
425 void PPB_FileIO_Proxy::OpenFileCallbackCompleteInHost(
426 int32_t pp_error,
427 const HostResource& host_resource) {
428 Send(new PpapiMsg_PPBFileIO_OpenFileComplete(kApiID, host_resource,
429 pp_error));
432 void PPB_FileIO_Proxy::QueryCallbackCompleteInHost(
433 int32_t pp_error,
434 const HostResource& host_resource,
435 PP_FileInfo* info) {
436 Send(new PpapiMsg_PPBFileIO_QueryComplete(kApiID, host_resource, pp_error,
437 *info));
438 delete info;
441 void PPB_FileIO_Proxy::ReadCallbackCompleteInHost(
442 int32_t pp_error,
443 const HostResource& host_resource,
444 std::string* data) {
445 // Only send the amount of data in the string that was actually read.
446 if (pp_error >= 0) {
447 DCHECK(pp_error <= static_cast<int32_t>(data->size()));
448 data->resize(pp_error);
450 Send(new PpapiMsg_PPBFileIO_ReadComplete(kApiID, host_resource, pp_error,
451 *data));
452 delete data;
454 #endif // !defined(OS_NACL)
456 } // namespace proxy
457 } // namespace ppapi