prune resources in MemoryCache
[chromium-blink-merge.git] / ppapi / proxy / file_io_resource.cc
blobe119dd5c621d51d49865b8339b6134acb3d3113e
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::File auto_close_file) {
45 } // namespace
47 namespace ppapi {
48 namespace proxy {
50 FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHolder> file_holder)
51 : file_holder_(file_holder) {
52 DCHECK(file_holder_.get());
55 FileIOResource::QueryOp::~QueryOp() {
58 int32_t FileIOResource::QueryOp::DoWork() {
59 return file_holder_->file()->GetInfo(&file_info_) ? PP_OK : PP_ERROR_FAILED;
62 FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHolder> file_holder,
63 int64_t offset,
64 int32_t bytes_to_read)
65 : file_holder_(file_holder),
66 offset_(offset),
67 bytes_to_read_(bytes_to_read) {
68 DCHECK(file_holder_.get());
71 FileIOResource::ReadOp::~ReadOp() {
74 int32_t FileIOResource::ReadOp::DoWork() {
75 DCHECK(!buffer_.get());
76 buffer_.reset(new char[bytes_to_read_]);
77 return file_holder_->file()->Read(offset_, buffer_.get(), bytes_to_read_);
80 FileIOResource::WriteOp::WriteOp(scoped_refptr<FileHolder> file_holder,
81 int64_t offset,
82 scoped_ptr<char[]> buffer,
83 int32_t bytes_to_write,
84 bool append)
85 : file_holder_(file_holder),
86 offset_(offset),
87 buffer_(buffer.Pass()),
88 bytes_to_write_(bytes_to_write),
89 append_(append) {
92 FileIOResource::WriteOp::~WriteOp() {
95 int32_t FileIOResource::WriteOp::DoWork() {
96 // In append mode, we can't call Write, since NaCl doesn't implement fcntl,
97 // causing the function to call pwrite, which is incorrect.
98 if (append_) {
99 return file_holder_->file()->WriteAtCurrentPos(buffer_.get(),
100 bytes_to_write_);
101 } else {
102 return file_holder_->file()->Write(offset_, buffer_.get(), bytes_to_write_);
106 FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
107 : PluginResource(connection, instance),
108 file_system_type_(PP_FILESYSTEMTYPE_INVALID),
109 open_flags_(0),
110 max_written_offset_(0),
111 append_mode_write_amount_(0),
112 check_quota_(false),
113 called_close_(false) {
114 SendCreate(BROWSER, PpapiHostMsg_FileIO_Create());
117 FileIOResource::~FileIOResource() {
118 Close();
121 PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
122 return this;
125 int32_t FileIOResource::Open(PP_Resource file_ref,
126 int32_t open_flags,
127 scoped_refptr<TrackedCallback> callback) {
128 EnterResourceNoLock<PPB_FileRef_API> enter_file_ref(file_ref, true);
129 if (enter_file_ref.failed())
130 return PP_ERROR_BADRESOURCE;
132 PPB_FileRef_API* file_ref_api = enter_file_ref.object();
133 const FileRefCreateInfo& create_info = file_ref_api->GetCreateInfo();
134 if (!FileSystemTypeIsValid(create_info.file_system_type)) {
135 NOTREACHED();
136 return PP_ERROR_FAILED;
138 int32_t rv = state_manager_.CheckOperationState(
139 FileIOStateManager::OPERATION_EXCLUSIVE, false);
140 if (rv != PP_OK)
141 return rv;
143 open_flags_ = open_flags;
144 file_system_type_ = create_info.file_system_type;
146 if (create_info.file_system_plugin_resource) {
147 EnterResourceNoLock<PPB_FileSystem_API> enter_file_system(
148 create_info.file_system_plugin_resource, true);
149 if (enter_file_system.failed())
150 return PP_ERROR_FAILED;
151 // Take a reference on the FileSystem resource. The FileIO host uses the
152 // FileSystem host for running tasks and checking quota.
153 file_system_resource_ = enter_file_system.resource();
156 // Take a reference on the FileRef resource while we're opening the file; we
157 // don't want the plugin destroying it during the Open operation.
158 file_ref_ = enter_file_ref.resource();
160 Call<PpapiPluginMsg_FileIO_OpenReply>(BROWSER,
161 PpapiHostMsg_FileIO_Open(
162 file_ref,
163 open_flags),
164 base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
165 callback));
167 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
168 return PP_OK_COMPLETIONPENDING;
171 int32_t FileIOResource::Query(PP_FileInfo* info,
172 scoped_refptr<TrackedCallback> callback) {
173 int32_t rv = state_manager_.CheckOperationState(
174 FileIOStateManager::OPERATION_EXCLUSIVE, true);
175 if (rv != PP_OK)
176 return rv;
177 if (!info)
178 return PP_ERROR_BADARGUMENT;
179 if (!FileHolder::IsValid(file_holder_))
180 return PP_ERROR_FAILED;
182 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
184 // If the callback is blocking, perform the task on the calling thread.
185 if (callback->is_blocking()) {
186 int32_t result = PP_ERROR_FAILED;
187 base::File::Info file_info;
188 // The plugin could release its reference to this instance when we release
189 // the proxy lock below.
190 scoped_refptr<FileIOResource> protect(this);
192 // Release the proxy lock while making a potentially slow file call.
193 ProxyAutoUnlock unlock;
194 if (file_holder_->file()->GetInfo(&file_info))
195 result = PP_OK;
197 if (result == PP_OK) {
198 // This writes the file info into the plugin's PP_FileInfo struct.
199 ppapi::FileInfoToPepperFileInfo(file_info,
200 file_system_type_,
201 info);
203 state_manager_.SetOperationFinished();
204 return result;
207 // For the non-blocking case, post a task to the file thread and add a
208 // completion task to write the result.
209 scoped_refptr<QueryOp> query_op(new QueryOp(file_holder_));
210 base::PostTaskAndReplyWithResult(
211 PpapiGlobals::Get()->GetFileTaskRunner(),
212 FROM_HERE,
213 Bind(&FileIOResource::QueryOp::DoWork, query_op),
214 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
215 callback->set_completion_task(
216 Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
218 return PP_OK_COMPLETIONPENDING;
221 int32_t FileIOResource::Touch(PP_Time last_access_time,
222 PP_Time last_modified_time,
223 scoped_refptr<TrackedCallback> callback) {
224 int32_t rv = state_manager_.CheckOperationState(
225 FileIOStateManager::OPERATION_EXCLUSIVE, true);
226 if (rv != PP_OK)
227 return rv;
229 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
230 PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time),
231 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
232 callback));
234 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
235 return PP_OK_COMPLETIONPENDING;
238 int32_t FileIOResource::Read(int64_t offset,
239 char* buffer,
240 int32_t bytes_to_read,
241 scoped_refptr<TrackedCallback> callback) {
242 int32_t rv = state_manager_.CheckOperationState(
243 FileIOStateManager::OPERATION_READ, true);
244 if (rv != PP_OK)
245 return rv;
247 PP_ArrayOutput output_adapter;
248 output_adapter.GetDataBuffer = &DummyGetDataBuffer;
249 output_adapter.user_data = buffer;
250 return ReadValidated(offset, bytes_to_read, output_adapter, callback);
253 int32_t FileIOResource::ReadToArray(int64_t offset,
254 int32_t max_read_length,
255 PP_ArrayOutput* array_output,
256 scoped_refptr<TrackedCallback> callback) {
257 DCHECK(array_output);
258 int32_t rv = state_manager_.CheckOperationState(
259 FileIOStateManager::OPERATION_READ, true);
260 if (rv != PP_OK)
261 return rv;
263 return ReadValidated(offset, max_read_length, *array_output, callback);
266 int32_t FileIOResource::Write(int64_t offset,
267 const char* buffer,
268 int32_t bytes_to_write,
269 scoped_refptr<TrackedCallback> callback) {
270 if (!buffer)
271 return PP_ERROR_FAILED;
272 if (offset < 0 || bytes_to_write < 0)
273 return PP_ERROR_FAILED;
274 if (!FileHolder::IsValid(file_holder_))
275 return PP_ERROR_FAILED;
277 int32_t rv = state_manager_.CheckOperationState(
278 FileIOStateManager::OPERATION_WRITE, true);
279 if (rv != PP_OK)
280 return rv;
282 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
284 if (check_quota_) {
285 int64_t increase = 0;
286 uint64_t max_offset = 0;
287 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0;
288 if (append) {
289 increase = bytes_to_write;
290 } else {
291 uint64_t max_offset = offset + bytes_to_write;
292 if (max_offset > static_cast<uint64_t>(kint64max))
293 return PP_ERROR_FAILED; // amount calculation would overflow.
294 increase = static_cast<int64_t>(max_offset) - max_written_offset_;
297 if (increase > 0) {
298 // Request a quota reservation. This makes the Write asynchronous, so we
299 // must copy the plugin's buffer.
300 scoped_ptr<char[]> copy(new char[bytes_to_write]);
301 memcpy(copy.get(), buffer, bytes_to_write);
302 int64_t result =
303 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
304 increase,
305 base::Bind(&FileIOResource::OnRequestWriteQuotaComplete,
306 this,
307 offset,
308 base::Passed(&copy),
309 bytes_to_write,
310 callback));
311 if (result == PP_OK_COMPLETIONPENDING)
312 return PP_OK_COMPLETIONPENDING;
313 DCHECK(result == increase);
315 if (append)
316 append_mode_write_amount_ += bytes_to_write;
317 else
318 max_written_offset_ = max_offset;
321 return WriteValidated(offset, buffer, bytes_to_write, callback);
324 int32_t FileIOResource::SetLength(int64_t length,
325 scoped_refptr<TrackedCallback> callback) {
326 int32_t rv = state_manager_.CheckOperationState(
327 FileIOStateManager::OPERATION_EXCLUSIVE, true);
328 if (rv != PP_OK)
329 return rv;
330 if (length < 0)
331 return PP_ERROR_FAILED;
333 if (check_quota_) {
334 int64_t increase = length - max_written_offset_;
335 if (increase > 0) {
336 int32_t result =
337 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
338 increase,
339 base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete,
340 this,
341 length, callback));
342 if (result == PP_OK_COMPLETIONPENDING) {
343 state_manager_.SetPendingOperation(
344 FileIOStateManager::OPERATION_EXCLUSIVE);
345 return PP_OK_COMPLETIONPENDING;
347 DCHECK(result == increase);
348 max_written_offset_ = length;
352 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
353 SetLengthValidated(length, callback);
354 return PP_OK_COMPLETIONPENDING;
357 int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) {
358 int32_t rv = state_manager_.CheckOperationState(
359 FileIOStateManager::OPERATION_EXCLUSIVE, true);
360 if (rv != PP_OK)
361 return rv;
363 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
364 PpapiHostMsg_FileIO_Flush(),
365 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
366 callback));
368 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
369 return PP_OK_COMPLETIONPENDING;
372 int64_t FileIOResource::GetMaxWrittenOffset() const {
373 return max_written_offset_;
376 int64_t FileIOResource::GetAppendModeWriteAmount() const {
377 return append_mode_write_amount_;
380 void FileIOResource::SetMaxWrittenOffset(int64_t max_written_offset) {
381 max_written_offset_ = max_written_offset;
384 void FileIOResource::SetAppendModeWriteAmount(
385 int64_t append_mode_write_amount) {
386 append_mode_write_amount_ = append_mode_write_amount;
389 void FileIOResource::Close() {
390 if (called_close_)
391 return;
393 called_close_ = true;
394 if (check_quota_) {
395 check_quota_ = false;
396 file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile(
397 pp_resource());
400 if (file_holder_.get())
401 file_holder_ = NULL;
403 Post(BROWSER, PpapiHostMsg_FileIO_Close(
404 FileGrowth(max_written_offset_, append_mode_write_amount_)));
407 int32_t FileIOResource::RequestOSFileHandle(
408 PP_FileHandle* handle,
409 scoped_refptr<TrackedCallback> callback) {
410 int32_t rv = state_manager_.CheckOperationState(
411 FileIOStateManager::OPERATION_EXCLUSIVE, true);
412 if (rv != PP_OK)
413 return rv;
415 Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER,
416 PpapiHostMsg_FileIO_RequestOSFileHandle(),
417 base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
418 callback, handle));
420 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
421 return PP_OK_COMPLETIONPENDING;
424 FileIOResource::FileHolder::FileHolder(PP_FileHandle file_handle)
425 : file_(file_handle) {
428 // static
429 bool FileIOResource::FileHolder::IsValid(
430 const scoped_refptr<FileIOResource::FileHolder>& handle) {
431 return handle.get() && handle->file_.IsValid();
434 FileIOResource::FileHolder::~FileHolder() {
435 if (file_.IsValid()) {
436 base::TaskRunner* file_task_runner =
437 PpapiGlobals::Get()->GetFileTaskRunner();
438 file_task_runner->PostTask(FROM_HERE,
439 base::Bind(&DoClose, Passed(&file_)));
443 int32_t FileIOResource::ReadValidated(int64_t offset,
444 int32_t bytes_to_read,
445 const PP_ArrayOutput& array_output,
446 scoped_refptr<TrackedCallback> callback) {
447 if (bytes_to_read < 0)
448 return PP_ERROR_FAILED;
449 if (!FileHolder::IsValid(file_holder_))
450 return PP_ERROR_FAILED;
452 state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
454 bytes_to_read = std::min(bytes_to_read, kMaxReadWriteSize);
455 if (callback->is_blocking()) {
456 char* buffer = static_cast<char*>(
457 array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1));
458 int32_t result = PP_ERROR_FAILED;
459 // The plugin could release its reference to this instance when we release
460 // the proxy lock below.
461 scoped_refptr<FileIOResource> protect(this);
462 if (buffer) {
463 // Release the proxy lock while making a potentially slow file call.
464 ProxyAutoUnlock unlock;
465 result = file_holder_->file()->Read(offset, buffer, bytes_to_read);
466 if (result < 0)
467 result = PP_ERROR_FAILED;
469 state_manager_.SetOperationFinished();
470 return result;
473 // For the non-blocking case, post a task to the file thread.
474 scoped_refptr<ReadOp> read_op(
475 new ReadOp(file_holder_, offset, bytes_to_read));
476 base::PostTaskAndReplyWithResult(
477 PpapiGlobals::Get()->GetFileTaskRunner(),
478 FROM_HERE,
479 Bind(&FileIOResource::ReadOp::DoWork, read_op),
480 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
481 callback->set_completion_task(
482 Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
484 return PP_OK_COMPLETIONPENDING;
487 int32_t FileIOResource::WriteValidated(
488 int64_t offset,
489 const char* buffer,
490 int32_t bytes_to_write,
491 scoped_refptr<TrackedCallback> callback) {
492 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0;
493 if (callback->is_blocking()) {
494 int32_t result;
496 // Release the proxy lock while making a potentially slow file call.
497 ProxyAutoUnlock unlock;
498 if (append) {
499 result = file_holder_->file()->WriteAtCurrentPos(buffer,
500 bytes_to_write);
501 } else {
502 result = file_holder_->file()->Write(offset, buffer, bytes_to_write);
505 if (result < 0)
506 result = PP_ERROR_FAILED;
508 state_manager_.SetOperationFinished();
509 return result;
512 // For the non-blocking case, post a task to the file thread. We must copy the
513 // plugin's buffer at this point.
514 scoped_ptr<char[]> copy(new char[bytes_to_write]);
515 memcpy(copy.get(), buffer, bytes_to_write);
516 scoped_refptr<WriteOp> write_op(
517 new WriteOp(file_holder_, offset, copy.Pass(), bytes_to_write, append));
518 base::PostTaskAndReplyWithResult(
519 PpapiGlobals::Get()->GetFileTaskRunner(),
520 FROM_HERE,
521 Bind(&FileIOResource::WriteOp::DoWork, write_op),
522 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
523 callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this));
525 return PP_OK_COMPLETIONPENDING;
528 void FileIOResource::SetLengthValidated(
529 int64_t length,
530 scoped_refptr<TrackedCallback> callback) {
531 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
532 PpapiHostMsg_FileIO_SetLength(length),
533 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
534 callback));
536 // On the browser side we grow |max_written_offset_| monotonically, due to the
537 // unpredictable ordering of plugin side Write and SetLength calls. Match that
538 // behavior here.
539 if (max_written_offset_ < length)
540 max_written_offset_ = length;
543 int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
544 PP_FileInfo* info,
545 int32_t result) {
546 DCHECK(state_manager_.get_pending_operation() ==
547 FileIOStateManager::OPERATION_EXCLUSIVE);
549 if (result == PP_OK) {
550 // This writes the file info into the plugin's PP_FileInfo struct.
551 ppapi::FileInfoToPepperFileInfo(query_op->file_info(),
552 file_system_type_,
553 info);
555 state_manager_.SetOperationFinished();
556 return result;
559 int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
560 PP_ArrayOutput array_output,
561 int32_t result) {
562 DCHECK(state_manager_.get_pending_operation() ==
563 FileIOStateManager::OPERATION_READ);
564 if (result >= 0) {
565 ArrayWriter output;
566 output.set_pp_array_output(array_output);
567 if (output.is_valid())
568 output.StoreArray(read_op->buffer(), result);
569 else
570 result = PP_ERROR_FAILED;
571 } else {
572 // The read operation failed.
573 result = PP_ERROR_FAILED;
575 state_manager_.SetOperationFinished();
576 return result;
579 void FileIOResource::OnRequestWriteQuotaComplete(
580 int64_t offset,
581 scoped_ptr<char[]> buffer,
582 int32_t bytes_to_write,
583 scoped_refptr<TrackedCallback> callback,
584 int64_t granted) {
585 DCHECK(granted >= 0);
586 if (granted == 0) {
587 callback->Run(PP_ERROR_NOQUOTA);
588 return;
590 if (open_flags_ & PP_FILEOPENFLAG_APPEND) {
591 DCHECK_LE(bytes_to_write, granted);
592 append_mode_write_amount_ += bytes_to_write;
593 } else {
594 DCHECK_LE(offset + bytes_to_write - max_written_offset_, granted);
596 int64_t max_offset = offset + bytes_to_write;
597 if (max_written_offset_ < max_offset)
598 max_written_offset_ = max_offset;
601 if (callback->is_blocking()) {
602 int32_t result =
603 WriteValidated(offset, buffer.get(), bytes_to_write, callback);
604 DCHECK(result != PP_OK_COMPLETIONPENDING);
605 callback->Run(result);
606 } else {
607 bool append = (open_flags_ & PP_FILEOPENFLAG_APPEND) != 0;
608 scoped_refptr<WriteOp> write_op(new WriteOp(
609 file_holder_, offset, buffer.Pass(), bytes_to_write, append));
610 base::PostTaskAndReplyWithResult(
611 PpapiGlobals::Get()->GetFileTaskRunner(),
612 FROM_HERE,
613 Bind(&FileIOResource::WriteOp::DoWork, write_op),
614 RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
615 callback->set_completion_task(Bind(&FileIOResource::OnWriteComplete, this));
619 void FileIOResource::OnRequestSetLengthQuotaComplete(
620 int64_t length,
621 scoped_refptr<TrackedCallback> callback,
622 int64_t granted) {
623 DCHECK(granted >= 0);
624 if (granted == 0) {
625 callback->Run(PP_ERROR_NOQUOTA);
626 return;
629 DCHECK_LE(length - max_written_offset_, granted);
630 if (max_written_offset_ < length)
631 max_written_offset_ = length;
632 SetLengthValidated(length, callback);
635 int32_t FileIOResource::OnWriteComplete(int32_t result) {
636 DCHECK(state_manager_.get_pending_operation() ==
637 FileIOStateManager::OPERATION_WRITE);
638 // |result| is the return value of WritePlatformFile; -1 indicates failure.
639 if (result < 0)
640 result = PP_ERROR_FAILED;
642 state_manager_.SetOperationFinished();
643 return result;
646 void FileIOResource::OnPluginMsgGeneralComplete(
647 scoped_refptr<TrackedCallback> callback,
648 const ResourceMessageReplyParams& params) {
649 DCHECK(state_manager_.get_pending_operation() ==
650 FileIOStateManager::OPERATION_EXCLUSIVE ||
651 state_manager_.get_pending_operation() ==
652 FileIOStateManager::OPERATION_WRITE);
653 // End this operation now, so the user's callback can execute another FileIO
654 // operation, assuming there are no other pending operations.
655 state_manager_.SetOperationFinished();
656 callback->Run(params.result());
659 void FileIOResource::OnPluginMsgOpenFileComplete(
660 scoped_refptr<TrackedCallback> callback,
661 const ResourceMessageReplyParams& params,
662 PP_Resource quota_file_system,
663 int64_t max_written_offset) {
664 DCHECK(state_manager_.get_pending_operation() ==
665 FileIOStateManager::OPERATION_EXCLUSIVE);
667 // Release the FileRef resource.
668 file_ref_ = NULL;
669 int32_t result = params.result();
670 if (result == PP_OK) {
671 state_manager_.SetOpenSucceed();
673 if (quota_file_system) {
674 DCHECK(quota_file_system == file_system_resource_->pp_resource());
675 check_quota_ = true;
676 max_written_offset_ = max_written_offset;
677 file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile(
678 pp_resource());
681 IPC::PlatformFileForTransit transit_file;
682 if (params.TakeFileHandleAtIndex(0, &transit_file)) {
683 file_holder_ = new FileHolder(
684 IPC::PlatformFileForTransitToPlatformFile(transit_file));
687 // End this operation now, so the user's callback can execute another FileIO
688 // operation, assuming there are no other pending operations.
689 state_manager_.SetOperationFinished();
690 callback->Run(result);
693 void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
694 scoped_refptr<TrackedCallback> callback,
695 PP_FileHandle* output_handle,
696 const ResourceMessageReplyParams& params) {
697 DCHECK(state_manager_.get_pending_operation() ==
698 FileIOStateManager::OPERATION_EXCLUSIVE);
700 if (!TrackedCallback::IsPending(callback)) {
701 state_manager_.SetOperationFinished();
702 return;
705 int32_t result = params.result();
706 IPC::PlatformFileForTransit transit_file;
707 if (!params.TakeFileHandleAtIndex(0, &transit_file))
708 result = PP_ERROR_FAILED;
709 *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
711 // End this operation now, so the user's callback can execute another FileIO
712 // operation, assuming there are no other pending operations.
713 state_manager_.SetOperationFinished();
714 callback->Run(result);
717 } // namespace proxy
718 } // namespace ppapi