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/file_io_resource.h"
8 #include "base/task_runner_util.h"
9 #include "ipc/ipc_message.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/proxy/ppapi_messages.h"
12 #include "ppapi/shared_impl/array_writer.h"
13 #include "ppapi/shared_impl/file_ref_create_info.h"
14 #include "ppapi/shared_impl/file_system_util.h"
15 #include "ppapi/shared_impl/file_type_conversion.h"
16 #include "ppapi/shared_impl/ppapi_globals.h"
17 #include "ppapi/shared_impl/proxy_lock.h"
18 #include "ppapi/shared_impl/resource_tracker.h"
19 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_file_ref_api.h"
21 #include "ppapi/thunk/ppb_file_system_api.h"
23 using ppapi::thunk::EnterResourceNoLock
;
24 using ppapi::thunk::PPB_FileIO_API
;
25 using ppapi::thunk::PPB_FileRef_API
;
26 using ppapi::thunk::PPB_FileSystem_API
;
30 // We must allocate a buffer sized according to the request of the plugin. To
31 // reduce the chance of out-of-memory errors, we cap the read and write size to
32 // 32MB. This is OK since the API specifies that it may perform a partial read
34 static const int32_t kMaxReadWriteSize
= 32 * 1024 * 1024; // 32MB
36 // An adapter to let Read() share the same implementation with ReadToArray().
37 void* DummyGetDataBuffer(void* user_data
, uint32_t count
, uint32_t size
) {
41 // File thread task to close the file handle.
42 void DoClose(base::PlatformFile file
) {
43 base::ClosePlatformFile(file
);
51 FileIOResource::QueryOp::QueryOp(scoped_refptr
<FileHandleHolder
> file_handle
)
52 : file_handle_(file_handle
) {
56 FileIOResource::QueryOp::~QueryOp() {
59 int32_t FileIOResource::QueryOp::DoWork() {
60 // TODO(rvargas): Convert this code to use base::File.
61 base::File
file(file_handle_
->raw_handle());
62 bool success
= file
.GetInfo(&file_info_
);
63 file
.TakePlatformFile();
64 return success
? PP_OK
: PP_ERROR_FAILED
;
67 FileIOResource::ReadOp::ReadOp(scoped_refptr
<FileHandleHolder
> file_handle
,
69 int32_t bytes_to_read
)
70 : file_handle_(file_handle
),
72 bytes_to_read_(bytes_to_read
) {
76 FileIOResource::ReadOp::~ReadOp() {
79 int32_t FileIOResource::ReadOp::DoWork() {
80 DCHECK(!buffer_
.get());
81 buffer_
.reset(new char[bytes_to_read_
]);
82 return base::ReadPlatformFile(
83 file_handle_
->raw_handle(), offset_
, buffer_
.get(), bytes_to_read_
);
86 FileIOResource::WriteOp::WriteOp(scoped_refptr
<FileHandleHolder
> file_handle
,
88 scoped_ptr
<char[]> buffer
,
89 int32_t bytes_to_write
,
91 : file_handle_(file_handle
),
93 buffer_(buffer
.Pass()),
94 bytes_to_write_(bytes_to_write
),
98 FileIOResource::WriteOp::~WriteOp() {
101 int32_t FileIOResource::WriteOp::DoWork() {
102 // In append mode, we can't call WritePlatformFile, since NaCl doesn't
103 // implement fcntl, causing the function to call pwrite, which is incorrect.
105 return base::WritePlatformFileAtCurrentPos(
106 file_handle_
->raw_handle(), buffer_
.get(), bytes_to_write_
);
108 return base::WritePlatformFile(
109 file_handle_
->raw_handle(), offset_
, buffer_
.get(), bytes_to_write_
);
113 FileIOResource::FileIOResource(Connection connection
, PP_Instance instance
)
114 : PluginResource(connection
, instance
),
115 file_system_type_(PP_FILESYSTEMTYPE_INVALID
),
117 max_written_offset_(0),
118 append_mode_write_amount_(0),
120 called_close_(false) {
121 SendCreate(BROWSER
, PpapiHostMsg_FileIO_Create());
124 FileIOResource::~FileIOResource() {
128 PPB_FileIO_API
* FileIOResource::AsPPB_FileIO_API() {
132 int32_t FileIOResource::Open(PP_Resource file_ref
,
134 scoped_refptr
<TrackedCallback
> callback
) {
135 EnterResourceNoLock
<PPB_FileRef_API
> enter_file_ref(file_ref
, true);
136 if (enter_file_ref
.failed())
137 return PP_ERROR_BADRESOURCE
;
139 PPB_FileRef_API
* file_ref_api
= enter_file_ref
.object();
140 const FileRefCreateInfo
& create_info
= file_ref_api
->GetCreateInfo();
141 if (!FileSystemTypeIsValid(create_info
.file_system_type
)) {
143 return PP_ERROR_FAILED
;
145 int32_t rv
= state_manager_
.CheckOperationState(
146 FileIOStateManager::OPERATION_EXCLUSIVE
, false);
150 open_flags_
= open_flags
;
151 file_system_type_
= create_info
.file_system_type
;
153 if (create_info
.file_system_plugin_resource
) {
154 EnterResourceNoLock
<PPB_FileSystem_API
> enter_file_system(
155 create_info
.file_system_plugin_resource
, true);
156 if (enter_file_system
.failed())
157 return PP_ERROR_FAILED
;
158 // Take a reference on the FileSystem resource. The FileIO host uses the
159 // FileSystem host for running tasks and checking quota.
160 file_system_resource_
= enter_file_system
.resource();
163 // Take a reference on the FileRef resource while we're opening the file; we
164 // don't want the plugin destroying it during the Open operation.
165 file_ref_
= enter_file_ref
.resource();
167 Call
<PpapiPluginMsg_FileIO_OpenReply
>(BROWSER
,
168 PpapiHostMsg_FileIO_Open(
171 base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete
, this,
174 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
175 return PP_OK_COMPLETIONPENDING
;
178 int32_t FileIOResource::Query(PP_FileInfo
* info
,
179 scoped_refptr
<TrackedCallback
> callback
) {
180 int32_t rv
= state_manager_
.CheckOperationState(
181 FileIOStateManager::OPERATION_EXCLUSIVE
, true);
185 return PP_ERROR_BADARGUMENT
;
186 if (!FileHandleHolder::IsValid(file_handle_
))
187 return PP_ERROR_FAILED
;
189 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
191 // If the callback is blocking, perform the task on the calling thread.
192 if (callback
->is_blocking()) {
193 int32_t result
= PP_ERROR_FAILED
;
194 base::File::Info file_info
;
195 // The plugin could release its reference to this instance when we release
196 // the proxy lock below.
197 scoped_refptr
<FileIOResource
> protect(this);
199 // Release the proxy lock while making a potentially slow file call.
200 ProxyAutoUnlock unlock
;
201 // TODO(rvargas): Convert this code to base::File.
202 base::File
file(file_handle_
->raw_handle());
203 bool success
= file
.GetInfo(&file_info
);
204 file
.TakePlatformFile();
208 if (result
== PP_OK
) {
209 // This writes the file info into the plugin's PP_FileInfo struct.
210 ppapi::FileInfoToPepperFileInfo(file_info
,
214 state_manager_
.SetOperationFinished();
218 // For the non-blocking case, post a task to the file thread and add a
219 // completion task to write the result.
220 scoped_refptr
<QueryOp
> query_op(new QueryOp(file_handle_
));
221 base::PostTaskAndReplyWithResult(
222 PpapiGlobals::Get()->GetFileTaskRunner(),
224 Bind(&FileIOResource::QueryOp::DoWork
, query_op
),
225 RunWhileLocked(Bind(&TrackedCallback::Run
, callback
)));
226 callback
->set_completion_task(
227 Bind(&FileIOResource::OnQueryComplete
, this, query_op
, info
));
229 return PP_OK_COMPLETIONPENDING
;
232 int32_t FileIOResource::Touch(PP_Time last_access_time
,
233 PP_Time last_modified_time
,
234 scoped_refptr
<TrackedCallback
> callback
) {
235 int32_t rv
= state_manager_
.CheckOperationState(
236 FileIOStateManager::OPERATION_EXCLUSIVE
, true);
240 Call
<PpapiPluginMsg_FileIO_GeneralReply
>(BROWSER
,
241 PpapiHostMsg_FileIO_Touch(last_access_time
, last_modified_time
),
242 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete
, this,
245 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
246 return PP_OK_COMPLETIONPENDING
;
249 int32_t FileIOResource::Read(int64_t offset
,
251 int32_t bytes_to_read
,
252 scoped_refptr
<TrackedCallback
> callback
) {
253 int32_t rv
= state_manager_
.CheckOperationState(
254 FileIOStateManager::OPERATION_READ
, true);
258 PP_ArrayOutput output_adapter
;
259 output_adapter
.GetDataBuffer
= &DummyGetDataBuffer
;
260 output_adapter
.user_data
= buffer
;
261 return ReadValidated(offset
, bytes_to_read
, output_adapter
, callback
);
264 int32_t FileIOResource::ReadToArray(int64_t offset
,
265 int32_t max_read_length
,
266 PP_ArrayOutput
* array_output
,
267 scoped_refptr
<TrackedCallback
> callback
) {
268 DCHECK(array_output
);
269 int32_t rv
= state_manager_
.CheckOperationState(
270 FileIOStateManager::OPERATION_READ
, true);
274 return ReadValidated(offset
, max_read_length
, *array_output
, callback
);
277 int32_t FileIOResource::Write(int64_t offset
,
279 int32_t bytes_to_write
,
280 scoped_refptr
<TrackedCallback
> callback
) {
282 return PP_ERROR_FAILED
;
283 if (offset
< 0 || bytes_to_write
< 0)
284 return PP_ERROR_FAILED
;
285 if (!FileHandleHolder::IsValid(file_handle_
))
286 return PP_ERROR_FAILED
;
288 int32_t rv
= state_manager_
.CheckOperationState(
289 FileIOStateManager::OPERATION_WRITE
, true);
293 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_WRITE
);
296 int64_t increase
= 0;
297 uint64_t max_offset
= 0;
298 bool append
= (open_flags_
& PP_FILEOPENFLAG_APPEND
) != 0;
300 increase
= bytes_to_write
;
302 uint64_t max_offset
= offset
+ bytes_to_write
;
303 if (max_offset
> static_cast<uint64_t>(kint64max
))
304 return PP_ERROR_FAILED
; // amount calculation would overflow.
305 increase
= static_cast<int64_t>(max_offset
) - max_written_offset_
;
309 // Request a quota reservation. This makes the Write asynchronous, so we
310 // must copy the plugin's buffer.
311 scoped_ptr
<char[]> copy(new char[bytes_to_write
]);
312 memcpy(copy
.get(), buffer
, bytes_to_write
);
314 file_system_resource_
->AsPPB_FileSystem_API()->RequestQuota(
316 base::Bind(&FileIOResource::OnRequestWriteQuotaComplete
,
322 if (result
== PP_OK_COMPLETIONPENDING
)
323 return PP_OK_COMPLETIONPENDING
;
324 DCHECK(result
== increase
);
327 append_mode_write_amount_
+= bytes_to_write
;
329 max_written_offset_
= max_offset
;
332 return WriteValidated(offset
, buffer
, bytes_to_write
, callback
);
335 int32_t FileIOResource::SetLength(int64_t length
,
336 scoped_refptr
<TrackedCallback
> callback
) {
337 int32_t rv
= state_manager_
.CheckOperationState(
338 FileIOStateManager::OPERATION_EXCLUSIVE
, true);
342 return PP_ERROR_FAILED
;
345 int64_t increase
= length
- max_written_offset_
;
348 file_system_resource_
->AsPPB_FileSystem_API()->RequestQuota(
350 base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete
,
353 if (result
== PP_OK_COMPLETIONPENDING
) {
354 state_manager_
.SetPendingOperation(
355 FileIOStateManager::OPERATION_EXCLUSIVE
);
356 return PP_OK_COMPLETIONPENDING
;
358 DCHECK(result
== increase
);
359 max_written_offset_
= length
;
363 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
364 SetLengthValidated(length
, callback
);
365 return PP_OK_COMPLETIONPENDING
;
368 int32_t FileIOResource::Flush(scoped_refptr
<TrackedCallback
> callback
) {
369 int32_t rv
= state_manager_
.CheckOperationState(
370 FileIOStateManager::OPERATION_EXCLUSIVE
, true);
374 Call
<PpapiPluginMsg_FileIO_GeneralReply
>(BROWSER
,
375 PpapiHostMsg_FileIO_Flush(),
376 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete
, this,
379 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
380 return PP_OK_COMPLETIONPENDING
;
383 int64_t FileIOResource::GetMaxWrittenOffset() const {
384 return max_written_offset_
;
387 int64_t FileIOResource::GetAppendModeWriteAmount() const {
388 return append_mode_write_amount_
;
391 void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset
) {
392 max_written_offset_
= max_written_offset
;
395 void FileIOResource::SetAppendModeWriteAmount(
396 int64_t append_mode_write_amount
) {
397 append_mode_write_amount_
= append_mode_write_amount
;
400 void FileIOResource::Close() {
404 called_close_
= true;
406 check_quota_
= false;
407 file_system_resource_
->AsPPB_FileSystem_API()->CloseQuotaFile(
414 Post(BROWSER
, PpapiHostMsg_FileIO_Close(
415 FileGrowth(max_written_offset_
, append_mode_write_amount_
)));
418 int32_t FileIOResource::RequestOSFileHandle(
419 PP_FileHandle
* handle
,
420 scoped_refptr
<TrackedCallback
> callback
) {
421 int32_t rv
= state_manager_
.CheckOperationState(
422 FileIOStateManager::OPERATION_EXCLUSIVE
, true);
426 Call
<PpapiPluginMsg_FileIO_RequestOSFileHandleReply
>(BROWSER
,
427 PpapiHostMsg_FileIO_RequestOSFileHandle(),
428 base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete
, this,
431 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE
);
432 return PP_OK_COMPLETIONPENDING
;
435 FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle
)
436 : raw_handle_(file_handle
) {
440 bool FileIOResource::FileHandleHolder::IsValid(
441 const scoped_refptr
<FileIOResource::FileHandleHolder
>& handle
) {
442 return handle
&& (handle
->raw_handle() != base::kInvalidPlatformFileValue
);
445 FileIOResource::FileHandleHolder::~FileHandleHolder() {
446 if (raw_handle_
!= base::kInvalidPlatformFileValue
) {
447 base::TaskRunner
* file_task_runner
=
448 PpapiGlobals::Get()->GetFileTaskRunner();
449 file_task_runner
->PostTask(FROM_HERE
,
450 base::Bind(&DoClose
, raw_handle_
));
454 int32_t FileIOResource::ReadValidated(int64_t offset
,
455 int32_t bytes_to_read
,
456 const PP_ArrayOutput
& array_output
,
457 scoped_refptr
<TrackedCallback
> callback
) {
458 if (bytes_to_read
< 0)
459 return PP_ERROR_FAILED
;
460 if (!FileHandleHolder::IsValid(file_handle_
))
461 return PP_ERROR_FAILED
;
463 state_manager_
.SetPendingOperation(FileIOStateManager::OPERATION_READ
);
465 bytes_to_read
= std::min(bytes_to_read
, kMaxReadWriteSize
);
466 if (callback
->is_blocking()) {
467 char* buffer
= static_cast<char*>(
468 array_output
.GetDataBuffer(array_output
.user_data
, bytes_to_read
, 1));
469 int32_t result
= PP_ERROR_FAILED
;
470 // The plugin could release its reference to this instance when we release
471 // the proxy lock below.
472 scoped_refptr
<FileIOResource
> protect(this);
474 // Release the proxy lock while making a potentially slow file call.
475 ProxyAutoUnlock unlock
;
476 result
= base::ReadPlatformFile(
477 file_handle_
->raw_handle(), offset
, buffer
, bytes_to_read
);
479 result
= PP_ERROR_FAILED
;
481 state_manager_
.SetOperationFinished();
485 // For the non-blocking case, post a task to the file thread.
486 scoped_refptr
<ReadOp
> read_op(
487 new ReadOp(file_handle_
, offset
, bytes_to_read
));
488 base::PostTaskAndReplyWithResult(
489 PpapiGlobals::Get()->GetFileTaskRunner(),
491 Bind(&FileIOResource::ReadOp::DoWork
, read_op
),
492 RunWhileLocked(Bind(&TrackedCallback::Run
, callback
)));
493 callback
->set_completion_task(
494 Bind(&FileIOResource::OnReadComplete
, this, read_op
, array_output
));
496 return PP_OK_COMPLETIONPENDING
;
499 int32_t FileIOResource::WriteValidated(
502 int32_t bytes_to_write
,
503 scoped_refptr
<TrackedCallback
> callback
) {
504 bool append
= (open_flags_
& PP_FILEOPENFLAG_APPEND
) != 0;
505 if (callback
->is_blocking()) {
508 // Release the proxy lock while making a potentially slow file call.
509 ProxyAutoUnlock unlock
;
511 result
= base::WritePlatformFileAtCurrentPos(
512 file_handle_
->raw_handle(), buffer
, bytes_to_write
);
514 result
= base::WritePlatformFile(
515 file_handle_
->raw_handle(), offset
, buffer
, bytes_to_write
);
519 result
= PP_ERROR_FAILED
;
521 state_manager_
.SetOperationFinished();
525 // For the non-blocking case, post a task to the file thread. We must copy the
526 // plugin's buffer at this point.
527 scoped_ptr
<char[]> copy(new char[bytes_to_write
]);
528 memcpy(copy
.get(), buffer
, bytes_to_write
);
529 scoped_refptr
<WriteOp
> write_op(
530 new WriteOp(file_handle_
, offset
, copy
.Pass(), bytes_to_write
, append
));
531 base::PostTaskAndReplyWithResult(
532 PpapiGlobals::Get()->GetFileTaskRunner(),
534 Bind(&FileIOResource::WriteOp::DoWork
, write_op
),
535 RunWhileLocked(Bind(&TrackedCallback::Run
, callback
)));
536 callback
->set_completion_task(Bind(&FileIOResource::OnWriteComplete
, this));
538 return PP_OK_COMPLETIONPENDING
;
541 void FileIOResource::SetLengthValidated(
543 scoped_refptr
<TrackedCallback
> callback
) {
544 Call
<PpapiPluginMsg_FileIO_GeneralReply
>(BROWSER
,
545 PpapiHostMsg_FileIO_SetLength(length
),
546 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete
, this,
549 // On the browser side we grow |max_written_offset_| monotonically, due to the
550 // unpredictable ordering of plugin side Write and SetLength calls. Match that
552 if (max_written_offset_
< length
)
553 max_written_offset_
= length
;
556 int32_t FileIOResource::OnQueryComplete(scoped_refptr
<QueryOp
> query_op
,
559 DCHECK(state_manager_
.get_pending_operation() ==
560 FileIOStateManager::OPERATION_EXCLUSIVE
);
562 if (result
== PP_OK
) {
563 // This writes the file info into the plugin's PP_FileInfo struct.
564 ppapi::FileInfoToPepperFileInfo(query_op
->file_info(),
568 state_manager_
.SetOperationFinished();
572 int32_t FileIOResource::OnReadComplete(scoped_refptr
<ReadOp
> read_op
,
573 PP_ArrayOutput array_output
,
575 DCHECK(state_manager_
.get_pending_operation() ==
576 FileIOStateManager::OPERATION_READ
);
579 output
.set_pp_array_output(array_output
);
580 if (output
.is_valid())
581 output
.StoreArray(read_op
->buffer(), result
);
583 result
= PP_ERROR_FAILED
;
585 // The read operation failed.
586 result
= PP_ERROR_FAILED
;
588 state_manager_
.SetOperationFinished();
592 void FileIOResource::OnRequestWriteQuotaComplete(
594 scoped_ptr
<char[]> buffer
,
595 int32_t bytes_to_write
,
596 scoped_refptr
<TrackedCallback
> callback
,
598 DCHECK(granted
>= 0);
600 callback
->Run(PP_ERROR_NOQUOTA
);
603 if (open_flags_
& PP_FILEOPENFLAG_APPEND
) {
604 DCHECK_LE(bytes_to_write
, granted
);
605 append_mode_write_amount_
+= bytes_to_write
;
607 DCHECK_LE(offset
+ bytes_to_write
- max_written_offset_
, granted
);
609 int64_t max_offset
= offset
+ bytes_to_write
;
610 if (max_written_offset_
< max_offset
)
611 max_written_offset_
= max_offset
;
614 if (callback
->is_blocking()) {
616 WriteValidated(offset
, buffer
.get(), bytes_to_write
, callback
);
617 DCHECK(result
!= PP_OK_COMPLETIONPENDING
);
618 callback
->Run(result
);
620 bool append
= (open_flags_
& PP_FILEOPENFLAG_APPEND
) != 0;
621 scoped_refptr
<WriteOp
> write_op(new WriteOp(
622 file_handle_
, offset
, buffer
.Pass(), bytes_to_write
, append
));
623 base::PostTaskAndReplyWithResult(
624 PpapiGlobals::Get()->GetFileTaskRunner(),
626 Bind(&FileIOResource::WriteOp::DoWork
, write_op
),
627 RunWhileLocked(Bind(&TrackedCallback::Run
, callback
)));
628 callback
->set_completion_task(Bind(&FileIOResource::OnWriteComplete
, this));
632 void FileIOResource::OnRequestSetLengthQuotaComplete(
634 scoped_refptr
<TrackedCallback
> callback
,
636 DCHECK(granted
>= 0);
638 callback
->Run(PP_ERROR_NOQUOTA
);
642 DCHECK_LE(length
- max_written_offset_
, granted
);
643 if (max_written_offset_
< length
)
644 max_written_offset_
= length
;
645 SetLengthValidated(length
, callback
);
648 int32_t FileIOResource::OnWriteComplete(int32_t result
) {
649 DCHECK(state_manager_
.get_pending_operation() ==
650 FileIOStateManager::OPERATION_WRITE
);
651 // |result| is the return value of WritePlatformFile; -1 indicates failure.
653 result
= PP_ERROR_FAILED
;
655 state_manager_
.SetOperationFinished();
659 void FileIOResource::OnPluginMsgGeneralComplete(
660 scoped_refptr
<TrackedCallback
> callback
,
661 const ResourceMessageReplyParams
& params
) {
662 DCHECK(state_manager_
.get_pending_operation() ==
663 FileIOStateManager::OPERATION_EXCLUSIVE
||
664 state_manager_
.get_pending_operation() ==
665 FileIOStateManager::OPERATION_WRITE
);
666 // End this operation now, so the user's callback can execute another FileIO
667 // operation, assuming there are no other pending operations.
668 state_manager_
.SetOperationFinished();
669 callback
->Run(params
.result());
672 void FileIOResource::OnPluginMsgOpenFileComplete(
673 scoped_refptr
<TrackedCallback
> callback
,
674 const ResourceMessageReplyParams
& params
,
675 PP_Resource quota_file_system
,
676 int64_t max_written_offset
) {
677 DCHECK(state_manager_
.get_pending_operation() ==
678 FileIOStateManager::OPERATION_EXCLUSIVE
);
680 // Release the FileRef resource.
682 int32_t result
= params
.result();
683 if (result
== PP_OK
) {
684 state_manager_
.SetOpenSucceed();
686 if (quota_file_system
) {
687 DCHECK(quota_file_system
== file_system_resource_
->pp_resource());
689 max_written_offset_
= max_written_offset
;
690 file_system_resource_
->AsPPB_FileSystem_API()->OpenQuotaFile(
694 IPC::PlatformFileForTransit transit_file
;
695 if (params
.TakeFileHandleAtIndex(0, &transit_file
)) {
696 file_handle_
= new FileHandleHolder(
697 IPC::PlatformFileForTransitToPlatformFile(transit_file
));
700 // End this operation now, so the user's callback can execute another FileIO
701 // operation, assuming there are no other pending operations.
702 state_manager_
.SetOperationFinished();
703 callback
->Run(result
);
706 void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
707 scoped_refptr
<TrackedCallback
> callback
,
708 PP_FileHandle
* output_handle
,
709 const ResourceMessageReplyParams
& params
) {
710 DCHECK(state_manager_
.get_pending_operation() ==
711 FileIOStateManager::OPERATION_EXCLUSIVE
);
713 if (!TrackedCallback::IsPending(callback
)) {
714 state_manager_
.SetOperationFinished();
718 int32_t result
= params
.result();
719 IPC::PlatformFileForTransit transit_file
;
720 if (!params
.TakeFileHandleAtIndex(0, &transit_file
))
721 result
= PP_ERROR_FAILED
;
722 *output_handle
= IPC::PlatformFileForTransitToPlatformFile(transit_file
);
724 // End this operation now, so the user's callback can execute another FileIO
725 // operation, assuming there are no other pending operations.
726 state_manager_
.SetOperationFinished();
727 callback
->Run(result
);