Revert 271602 "Implementation of leveldb-backed PrefStore."
[chromium-blink-merge.git] / ppapi / proxy / file_io_resource.cc
blob715757421e1ed326aa235622e881231c0825cead
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"
7 #include "base/bind.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;
28 namespace {
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
33 // or write.
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) {
38 return user_data;
41 // File thread task to close the file handle.
42 void DoClose(base::PlatformFile file) {
43 base::ClosePlatformFile(file);
46 } // namespace
48 namespace ppapi {
49 namespace proxy {
51 FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHandleHolder> file_handle)
52 : file_handle_(file_handle) {
53 DCHECK(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,
68 int64_t offset,
69 int32_t bytes_to_read)
70 : file_handle_(file_handle),
71 offset_(offset),
72 bytes_to_read_(bytes_to_read) {
73 DCHECK(file_handle_);
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,
87 int64_t offset,
88 const char* buffer,
89 int32_t bytes_to_write,
90 bool append)
91 : file_handle_(file_handle),
92 offset_(offset),
93 buffer_(buffer),
94 bytes_to_write_(bytes_to_write),
95 append_(append) {
98 FileIOResource::WriteOp::~WriteOp() {
101 int32_t FileIOResource::WriteOp::DoWork() {
102 // We can't just call WritePlatformFile in append mode, since NaCl doesn't
103 // implement fcntl, causing the function to call pwrite, which is incorrect.
104 if (append_) {
105 return base::WritePlatformFileAtCurrentPos(
106 file_handle_->raw_handle(), buffer_, bytes_to_write_);
107 } else {
108 return base::WritePlatformFile(
109 file_handle_->raw_handle(), offset_, buffer_, bytes_to_write_);
113 FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
114 : PluginResource(connection, instance),
115 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
116 open_flags_(0),
117 max_written_offset_(0),
118 append_mode_write_amount_(0),
119 check_quota_(false),
120 called_close_(false) {
121 SendCreate(BROWSER, PpapiHostMsg_FileIO_Create());
124 FileIOResource::~FileIOResource() {
125 Close();
128 PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
129 return this;
132 int32_t FileIOResource::Open(PP_Resource file_ref,
133 int32_t open_flags,
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)) {
142 NOTREACHED();
143 return PP_ERROR_FAILED;
145 int32_t rv = state_manager_.CheckOperationState(
146 FileIOStateManager::OPERATION_EXCLUSIVE, false);
147 if (rv != PP_OK)
148 return rv;
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(
169 file_ref,
170 open_flags),
171 base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
172 callback));
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);
182 if (rv != PP_OK)
183 return rv;
184 if (!info)
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();
205 if (success)
206 result = PP_OK;
208 if (result == PP_OK) {
209 // This writes the file info into the plugin's PP_FileInfo struct.
210 ppapi::FileInfoToPepperFileInfo(file_info,
211 file_system_type_,
212 info);
214 state_manager_.SetOperationFinished();
215 return result;
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(),
223 FROM_HERE,
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);
237 if (rv != PP_OK)
238 return rv;
240 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
241 PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time),
242 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
243 callback));
245 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
246 return PP_OK_COMPLETIONPENDING;
249 int32_t FileIOResource::Read(int64_t offset,
250 char* buffer,
251 int32_t bytes_to_read,
252 scoped_refptr<TrackedCallback> callback) {
253 int32_t rv = state_manager_.CheckOperationState(
254 FileIOStateManager::OPERATION_READ, true);
255 if (rv != PP_OK)
256 return rv;
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);
271 if (rv != PP_OK)
272 return rv;
274 return ReadValidated(offset, max_read_length, *array_output, callback);
277 int32_t FileIOResource::Write(int64_t offset,
278 const char* buffer,
279 int32_t bytes_to_write,
280 scoped_refptr<TrackedCallback> callback) {
281 if (!buffer)
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);
290 if (rv != PP_OK)
291 return rv;
293 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
295 if (check_quota_) {
296 int64_t increase = 0;
297 uint64_t max_offset = 0;
298 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0;
299 if (append) {
300 increase = bytes_to_write;
301 } else {
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_;
308 if (increase > 0) {
309 int64_t result =
310 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
311 increase,
312 base::Bind(&FileIOResource::OnRequestWriteQuotaComplete,
313 this,
314 offset, buffer, bytes_to_write, callback));
315 if (result == PP_OK_COMPLETIONPENDING)
316 return PP_OK_COMPLETIONPENDING;
317 DCHECK(result == increase);
319 if (append)
320 append_mode_write_amount_ += bytes_to_write;
321 else
322 max_written_offset_ = max_offset;
325 return WriteValidated(offset, buffer, bytes_to_write, callback);
328 int32_t FileIOResource::SetLength(int64_t length,
329 scoped_refptr<TrackedCallback> callback) {
330 int32_t rv = state_manager_.CheckOperationState(
331 FileIOStateManager::OPERATION_EXCLUSIVE, true);
332 if (rv != PP_OK)
333 return rv;
334 if (length < 0)
335 return PP_ERROR_FAILED;
337 if (check_quota_) {
338 int64_t increase = length - max_written_offset_;
339 if (increase > 0) {
340 int32_t result =
341 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
342 increase,
343 base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete,
344 this,
345 length, callback));
346 if (result == PP_OK_COMPLETIONPENDING) {
347 state_manager_.SetPendingOperation(
348 FileIOStateManager::OPERATION_EXCLUSIVE);
349 return PP_OK_COMPLETIONPENDING;
351 DCHECK(result == increase);
352 max_written_offset_ = length;
356 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
357 SetLengthValidated(length, callback);
358 return PP_OK_COMPLETIONPENDING;
361 int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) {
362 int32_t rv = state_manager_.CheckOperationState(
363 FileIOStateManager::OPERATION_EXCLUSIVE, true);
364 if (rv != PP_OK)
365 return rv;
367 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
368 PpapiHostMsg_FileIO_Flush(),
369 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
370 callback));
372 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
373 return PP_OK_COMPLETIONPENDING;
376 int64_t FileIOResource::GetMaxWrittenOffset() const {
377 return max_written_offset_;
380 int64_t FileIOResource::GetAppendModeWriteAmount() const {
381 return append_mode_write_amount_;
384 void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset) {
385 max_written_offset_ = max_written_offset;
388 void FileIOResource::SetAppendModeWriteAmount(
389 int64_t append_mode_write_amount) {
390 append_mode_write_amount_ = append_mode_write_amount;
393 void FileIOResource::Close() {
394 if (called_close_)
395 return;
397 called_close_ = true;
398 if (check_quota_) {
399 check_quota_ = false;
400 file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile(
401 pp_resource());
404 if (file_handle_)
405 file_handle_ = NULL;
407 Post(BROWSER, PpapiHostMsg_FileIO_Close(
408 FileGrowth(max_written_offset_, append_mode_write_amount_)));
411 int32_t FileIOResource::RequestOSFileHandle(
412 PP_FileHandle* handle,
413 scoped_refptr<TrackedCallback> callback) {
414 int32_t rv = state_manager_.CheckOperationState(
415 FileIOStateManager::OPERATION_EXCLUSIVE, true);
416 if (rv != PP_OK)
417 return rv;
419 Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER,
420 PpapiHostMsg_FileIO_RequestOSFileHandle(),
421 base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
422 callback, handle));
424 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
425 return PP_OK_COMPLETIONPENDING;
428 FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle)
429 : raw_handle_(file_handle) {
432 // static
433 bool FileIOResource::FileHandleHolder::IsValid(
434 const scoped_refptr<FileIOResource::FileHandleHolder>& handle) {
435 return handle && (handle->raw_handle() != base::kInvalidPlatformFileValue);
438 FileIOResource::FileHandleHolder::~FileHandleHolder() {
439 if (raw_handle_ != base::kInvalidPlatformFileValue) {
440 base::TaskRunner* file_task_runner =
441 PpapiGlobals::Get()->GetFileTaskRunner();
442 file_task_runner->PostTask(FROM_HERE,
443 base::Bind(&DoClose, raw_handle_));
447 int32_t FileIOResource::ReadValidated(int64_t offset,
448 int32_t bytes_to_read,
449 const PP_ArrayOutput& array_output,
450 scoped_refptr<TrackedCallback> callback) {
451 if (bytes_to_read < 0)
452 return PP_ERROR_FAILED;
453 if (!FileHandleHolder::IsValid(file_handle_))
454 return PP_ERROR_FAILED;
456 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
458 bytes_to_read = std::min(bytes_to_read, kMaxReadWriteSize);
459 if (callback->is_blocking()) {
460 char* buffer = static_cast<char*>(
461 array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1));
462 int32_t result = PP_ERROR_FAILED;
463 // The plugin could release its reference to this instance when we release
464 // the proxy lock below.
465 scoped_refptr<FileIOResource> protect(this);
466 if (buffer) {
467 // Release the proxy lock while making a potentially slow file call.
468 ProxyAutoUnlock unlock;
469 result = base::ReadPlatformFile(
470 file_handle_->raw_handle(), offset, buffer, bytes_to_read);
471 if (result < 0)
472 result = PP_ERROR_FAILED;
474 state_manager_.SetOperationFinished();
475 return result;
478 // For the non-blocking case, post a task to the file thread.
479 scoped_refptr<ReadOp> read_op(
480 new ReadOp(file_handle_, offset, bytes_to_read));
481 base::PostTaskAndReplyWithResult(
482 PpapiGlobals::Get()->GetFileTaskRunner(),
483 FROM_HERE,
484 Bind(&FileIOResource::ReadOp::DoWork, read_op),
485 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
486 callback->set_completion_task(
487 Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
489 return PP_OK_COMPLETIONPENDING;
492 int32_t FileIOResource::WriteValidated(
493 int64_t offset,
494 const char* buffer,
495 int32_t bytes_to_write,
496 scoped_refptr<TrackedCallback> callback) {
497 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0;
498 if (callback->is_blocking()) {
499 int32_t result;
501 // Release the proxy lock while making a potentially slow file call.
502 ProxyAutoUnlock unlock;
503 if (append) {
504 result = base::WritePlatformFileAtCurrentPos(
505 file_handle_->raw_handle(), buffer, bytes_to_write);
506 } else {
507 result = base::WritePlatformFile(
508 file_handle_->raw_handle(), offset, buffer, bytes_to_write);
511 if (result < 0)
512 result = PP_ERROR_FAILED;
514 state_manager_.SetOperationFinished();
515 return result;
518 // For the non-blocking case, post a task to the file thread.
519 scoped_refptr<WriteOp> write_op(
520 new WriteOp(file_handle_, offset, buffer, bytes_to_write, append));
521 base::PostTaskAndReplyWithResult(
522 PpapiGlobals::Get()->GetFileTaskRunner(),
523 FROM_HERE,
524 Bind(&FileIOResource::WriteOp::DoWork, write_op),
525 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
526 callback->set_completion_task(
527 Bind(&FileIOResource::OnWriteComplete, this, write_op));
529 return PP_OK_COMPLETIONPENDING;
532 void FileIOResource::SetLengthValidated(
533 int64_t length,
534 scoped_refptr<TrackedCallback> callback) {
535 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
536 PpapiHostMsg_FileIO_SetLength(length),
537 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
538 callback));
540 // On the browser side we grow |max_written_offset_| monotonically, due to the
541 // unpredictable ordering of plugin side Write and SetLength calls. Match that
542 // behavior here.
543 if (max_written_offset_ < length)
544 max_written_offset_ = length;
547 int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
548 PP_FileInfo* info,
549 int32_t result) {
550 DCHECK(state_manager_.get_pending_operation() ==
551 FileIOStateManager::OPERATION_EXCLUSIVE);
553 if (result == PP_OK) {
554 // This writes the file info into the plugin's PP_FileInfo struct.
555 ppapi::FileInfoToPepperFileInfo(query_op->file_info(),
556 file_system_type_,
557 info);
559 state_manager_.SetOperationFinished();
560 return result;
563 int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
564 PP_ArrayOutput array_output,
565 int32_t result) {
566 DCHECK(state_manager_.get_pending_operation() ==
567 FileIOStateManager::OPERATION_READ);
568 if (result >= 0) {
569 ArrayWriter output;
570 output.set_pp_array_output(array_output);
571 if (output.is_valid())
572 output.StoreArray(read_op->buffer(), result);
573 else
574 result = PP_ERROR_FAILED;
575 } else {
576 // The read operation failed.
577 result = PP_ERROR_FAILED;
579 state_manager_.SetOperationFinished();
580 return result;
583 void FileIOResource::OnRequestWriteQuotaComplete(
584 int64_t offset,
585 const char* buffer,
586 int32_t bytes_to_write,
587 scoped_refptr<TrackedCallback> callback,
588 int64_t granted) {
589 DCHECK(granted >= 0);
590 if (granted == 0) {
591 callback->Run(PP_ERROR_NOQUOTA);
592 return;
594 if (open_flags_ & PP_FILEOPENFLAG_APPEND) {
595 DCHECK_LE(bytes_to_write, granted);
596 append_mode_write_amount_ += bytes_to_write;
597 } else {
598 DCHECK_LE(offset + bytes_to_write - max_written_offset_, granted);
600 int64_t max_offset = offset + bytes_to_write;
601 if (max_written_offset_ < max_offset)
602 max_written_offset_ = max_offset;
605 int32_t result = WriteValidated(offset, buffer, bytes_to_write, callback);
606 if (result != PP_OK_COMPLETIONPENDING)
607 callback->Run(result);
610 void FileIOResource::OnRequestSetLengthQuotaComplete(
611 int64_t length,
612 scoped_refptr<TrackedCallback> callback,
613 int64_t granted) {
614 DCHECK(granted >= 0);
615 if (granted == 0) {
616 callback->Run(PP_ERROR_NOQUOTA);
617 return;
620 DCHECK_LE(length - max_written_offset_, granted);
621 if (max_written_offset_ < length)
622 max_written_offset_ = length;
623 SetLengthValidated(length, callback);
626 int32_t FileIOResource::OnWriteComplete(scoped_refptr<WriteOp> write_op,
627 int32_t result) {
628 DCHECK(state_manager_.get_pending_operation() ==
629 FileIOStateManager::OPERATION_WRITE);
630 // |result| is the return value of WritePlatformFile; -1 indicates failure.
631 if (result < 0)
632 result = PP_ERROR_FAILED;
634 state_manager_.SetOperationFinished();
635 return result;
638 void FileIOResource::OnPluginMsgGeneralComplete(
639 scoped_refptr<TrackedCallback> callback,
640 const ResourceMessageReplyParams& params) {
641 DCHECK(state_manager_.get_pending_operation() ==
642 FileIOStateManager::OPERATION_EXCLUSIVE ||
643 state_manager_.get_pending_operation() ==
644 FileIOStateManager::OPERATION_WRITE);
645 // End this operation now, so the user's callback can execute another FileIO
646 // operation, assuming there are no other pending operations.
647 state_manager_.SetOperationFinished();
648 callback->Run(params.result());
651 void FileIOResource::OnPluginMsgOpenFileComplete(
652 scoped_refptr<TrackedCallback> callback,
653 const ResourceMessageReplyParams& params,
654 PP_Resource quota_file_system,
655 int64_t max_written_offset) {
656 DCHECK(state_manager_.get_pending_operation() ==
657 FileIOStateManager::OPERATION_EXCLUSIVE);
659 // Release the FileRef resource.
660 file_ref_ = NULL;
661 int32_t result = params.result();
662 if (result == PP_OK) {
663 state_manager_.SetOpenSucceed();
665 if (quota_file_system) {
666 DCHECK(quota_file_system == file_system_resource_->pp_resource());
667 check_quota_ = true;
668 max_written_offset_ = max_written_offset;
669 file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile(
670 pp_resource());
673 IPC::PlatformFileForTransit transit_file;
674 if (params.TakeFileHandleAtIndex(0, &transit_file)) {
675 file_handle_ = new FileHandleHolder(
676 IPC::PlatformFileForTransitToPlatformFile(transit_file));
679 // End this operation now, so the user's callback can execute another FileIO
680 // operation, assuming there are no other pending operations.
681 state_manager_.SetOperationFinished();
682 callback->Run(result);
685 void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
686 scoped_refptr<TrackedCallback> callback,
687 PP_FileHandle* output_handle,
688 const ResourceMessageReplyParams& params) {
689 DCHECK(state_manager_.get_pending_operation() ==
690 FileIOStateManager::OPERATION_EXCLUSIVE);
692 if (!TrackedCallback::IsPending(callback)) {
693 state_manager_.SetOperationFinished();
694 return;
697 int32_t result = params.result();
698 IPC::PlatformFileForTransit transit_file;
699 if (!params.TakeFileHandleAtIndex(0, &transit_file))
700 result = PP_ERROR_FAILED;
701 *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
703 // End this operation now, so the user's callback can execute another FileIO
704 // operation, assuming there are no other pending operations.
705 state_manager_.SetOperationFinished();
706 callback->Run(result);
709 } // namespace proxy
710 } // namespace ppapi