Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.
[chromium-blink-merge.git] / ppapi / proxy / file_io_resource.cc
blob0564fdfbb69364e39454b973ab70058bcc5aa132
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 scoped_ptr<char[]> buffer,
89 int32_t bytes_to_write,
90 bool append)
91 : file_handle_(file_handle),
92 offset_(offset),
93 buffer_(buffer.Pass()),
94 bytes_to_write_(bytes_to_write),
95 append_(append) {
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.
104 if (append_) {
105 return base::WritePlatformFileAtCurrentPos(
106 file_handle_->raw_handle(), buffer_.get(), bytes_to_write_);
107 } else {
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),
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 // 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);
313 int64_t result =
314 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
315 increase,
316 base::Bind(&FileIOResource::OnRequestWriteQuotaComplete,
317 this,
318 offset,
319 base::Passed(&copy),
320 bytes_to_write,
321 callback));
322 if (result == PP_OK_COMPLETIONPENDING)
323 return PP_OK_COMPLETIONPENDING;
324 DCHECK(result == increase);
326 if (append)
327 append_mode_write_amount_ += bytes_to_write;
328 else
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);
339 if (rv != PP_OK)
340 return rv;
341 if (length < 0)
342 return PP_ERROR_FAILED;
344 if (check_quota_) {
345 int64_t increase = length - max_written_offset_;
346 if (increase > 0) {
347 int32_t result =
348 file_system_resource_->AsPPB_FileSystem_API()->RequestQuota(
349 increase,
350 base::Bind(&FileIOResource::OnRequestSetLengthQuotaComplete,
351 this,
352 length, callback));
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);
371 if (rv != PP_OK)
372 return rv;
374 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
375 PpapiHostMsg_FileIO_Flush(),
376 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
377 callback));
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() {
401 if (called_close_)
402 return;
404 called_close_ = true;
405 if (check_quota_) {
406 check_quota_ = false;
407 file_system_resource_->AsPPB_FileSystem_API()->CloseQuotaFile(
408 pp_resource());
411 if (file_handle_)
412 file_handle_ = NULL;
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);
423 if (rv != PP_OK)
424 return rv;
426 Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER,
427 PpapiHostMsg_FileIO_RequestOSFileHandle(),
428 base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
429 callback, handle));
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) {
439 // static
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);
473 if (buffer) {
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);
478 if (result < 0)
479 result = PP_ERROR_FAILED;
481 state_manager_.SetOperationFinished();
482 return result;
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(),
490 FROM_HERE,
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(
500 int64_t offset,
501 const char* buffer,
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()) {
506 int32_t result;
508 // Release the proxy lock while making a potentially slow file call.
509 ProxyAutoUnlock unlock;
510 if (append) {
511 result = base::WritePlatformFileAtCurrentPos(
512 file_handle_->raw_handle(), buffer, bytes_to_write);
513 } else {
514 result = base::WritePlatformFile(
515 file_handle_->raw_handle(), offset, buffer, bytes_to_write);
518 if (result < 0)
519 result = PP_ERROR_FAILED;
521 state_manager_.SetOperationFinished();
522 return result;
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(),
533 FROM_HERE,
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(
542 int64_t length,
543 scoped_refptr<TrackedCallback> callback) {
544 Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
545 PpapiHostMsg_FileIO_SetLength(length),
546 base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
547 callback));
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
551 // behavior here.
552 if (max_written_offset_ < length)
553 max_written_offset_ = length;
556 int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
557 PP_FileInfo* info,
558 int32_t result) {
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(),
565 file_system_type_,
566 info);
568 state_manager_.SetOperationFinished();
569 return result;
572 int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
573 PP_ArrayOutput array_output,
574 int32_t result) {
575 DCHECK(state_manager_.get_pending_operation() ==
576 FileIOStateManager::OPERATION_READ);
577 if (result >= 0) {
578 ArrayWriter output;
579 output.set_pp_array_output(array_output);
580 if (output.is_valid())
581 output.StoreArray(read_op->buffer(), result);
582 else
583 result = PP_ERROR_FAILED;
584 } else {
585 // The read operation failed.
586 result = PP_ERROR_FAILED;
588 state_manager_.SetOperationFinished();
589 return result;
592 void FileIOResource::OnRequestWriteQuotaComplete(
593 int64_t offset,
594 scoped_ptr<char[]> buffer,
595 int32_t bytes_to_write,
596 scoped_refptr<TrackedCallback> callback,
597 int64_t granted) {
598 DCHECK(granted >= 0);
599 if (granted == 0) {
600 callback->Run(PP_ERROR_NOQUOTA);
601 return;
603 if (open_flags_ & PP_FILEOPENFLAG_APPEND) {
604 DCHECK_LE(bytes_to_write, granted);
605 append_mode_write_amount_ += bytes_to_write;
606 } else {
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()) {
615 int32_t result =
616 WriteValidated(offset, buffer.get(), bytes_to_write, callback);
617 DCHECK(result != PP_OK_COMPLETIONPENDING);
618 callback->Run(result);
619 } else {
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(),
625 FROM_HERE,
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(
633 int64_t length,
634 scoped_refptr<TrackedCallback> callback,
635 int64_t granted) {
636 DCHECK(granted >= 0);
637 if (granted == 0) {
638 callback->Run(PP_ERROR_NOQUOTA);
639 return;
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.
652 if (result < 0)
653 result = PP_ERROR_FAILED;
655 state_manager_.SetOperationFinished();
656 return result;
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.
681 file_ref_ = NULL;
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());
688 check_quota_ = true;
689 max_written_offset_ = max_written_offset;
690 file_system_resource_->AsPPB_FileSystem_API()->OpenQuotaFile(
691 pp_resource());
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();
715 return;
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);
730 } // namespace proxy
731 } // namespace ppapi