file_io_resource.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/file_io_resource.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/task_runner_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_message.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/c/pp_errors.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/array_writer.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/file_type_conversion.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/proxy_lock.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/enter.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/ppb_file_ref_api.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileIO_API;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileRef_API;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We must allocate a buffer sized according to the request of the plugin. To
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// reduce the chance of out-of-memory errors, we cap the read size to 32MB.
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// This is OK since the API specifies that it may perform a partial read.
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const int32_t kMaxReadSize = 32 * 1024 * 1024;  // 32MB
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An adapter to let Read() share the same implementation with ReadToArray().
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_data;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// File thread task to close the file handle.
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DoClose(base::PlatformFile file) {
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::ClosePlatformFile(file);
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ppapi {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace proxy {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHandleHolder> file_handle)
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : file_handle_(file_handle) {
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(file_handle_);
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::QueryOp::~QueryOp() {
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::QueryOp::DoWork() {
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info_) ?
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      PP_OK : PP_ERROR_FAILED;
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHandleHolder> file_handle,
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                               int64_t offset,
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                               int32_t bytes_to_read)
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : file_handle_(file_handle),
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    offset_(offset),
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bytes_to_read_(bytes_to_read) {
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(file_handle_);
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::ReadOp::~ReadOp() {
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::ReadOp::DoWork() {
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!buffer_.get());
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  buffer_.reset(new char[bytes_to_read_]);
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return base::ReadPlatformFile(
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      file_handle_->raw_handle(), offset_, buffer_.get(), bytes_to_read_);
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : PluginResource(connection, instance),
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      file_system_type_(PP_FILESYSTEMTYPE_INVALID) {
810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  SendCreate(BROWSER, PpapiHostMsg_FileIO_Create());
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::~FileIOResource() {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return this;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Open(PP_Resource file_ref,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int32_t open_flags,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             scoped_refptr<TrackedCallback> callback) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enter.failed())
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PP_ERROR_BADRESOURCE;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PPB_FileRef_API* file_ref_api = enter.object();
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PP_FileSystemType type = file_ref_api->GetFileSystemType();
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      type != PP_FILESYSTEMTYPE_EXTERNAL &&
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      type != PP_FILESYSTEMTYPE_ISOLATED) {
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NOTREACHED();
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  file_system_type_ = type;
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, false);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Take a reference on the FileRef resource while we're opening the file; we
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // don't want the plugin destroying it during the Open operation.
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  file_ref_ = enter.resource();
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_OpenReply>(BROWSER,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Open(
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          file_ref,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          open_flags),
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Query(PP_FileInfo* info,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!info)
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_BADARGUMENT;
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!FileHandleHolder::IsValid(file_handle_))
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If the callback is blocking, perform the task on the calling thread.
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (callback->is_blocking()) {
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int32_t result = PP_ERROR_FAILED;
1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::PlatformFileInfo file_info;
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The plugin could release its reference to this instance when we release
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // the proxy lock below.
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<FileIOResource> protect(this);
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    {
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Release the proxy lock while making a potentially slow file call.
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ProxyAutoUnlock unlock;
1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info))
1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        result = PP_OK;
1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (result == PP_OK) {
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // This writes the file info into the plugin's PP_FileInfo struct.
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ppapi::PlatformFileInfoToPepperFileInfo(file_info,
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              file_system_type_,
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              info);
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    state_manager_.SetOperationFinished();
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return result;
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // For the non-blocking case, post a task to the file thread and add a
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // completion task to write the result.
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_));
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::PostTaskAndReplyWithResult(
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      PpapiGlobals::Get()->GetFileTaskRunner(),
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::QueryOp::DoWork, query_op),
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  callback->set_completion_task(
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Touch(PP_Time last_access_time,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              PP_Time last_modified_time,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time),
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Read(int64_t offset,
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             char* buffer,
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int32_t bytes_to_read,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             scoped_refptr<TrackedCallback> callback) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_READ, true);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_ArrayOutput output_adapter;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_adapter.GetDataBuffer = &DummyGetDataBuffer;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_adapter.user_data = buffer;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ReadValidated(offset, bytes_to_read, output_adapter, callback);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadToArray(int64_t offset,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int32_t max_read_length,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    PP_ArrayOutput* array_output,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    scoped_refptr<TrackedCallback> callback) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(array_output);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_READ, true);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ReadValidated(offset, max_read_length, *array_output, callback);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Write(int64_t offset,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const char* buffer,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              int32_t bytes_to_write,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_WRITE, true);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(brettw) it would be nice to use a shared memory buffer for large
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // writes rather than having to copy to a string (which will involve a number
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of extra copies to serialize over IPC).
2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Write(offset, std::string(buffer, bytes_to_write)),
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::SetLength(int64_t length,
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  scoped_refptr<TrackedCallback> callback) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_SetLength(length),
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Flush(),
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::Close() {
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (file_handle_) {
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_handle_ = NULL;
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Post(BROWSER, PpapiHostMsg_FileIO_Close());
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::RequestOSFileHandle(
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PP_FileHandle* handle,
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_refptr<TrackedCallback> callback) {
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int32_t rv = state_manager_.CheckOperationState(
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FileIOStateManager::OPERATION_EXCLUSIVE, true);
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (rv != PP_OK)
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return rv;
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER,
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      PpapiHostMsg_FileIO_RequestOSFileHandle(),
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 callback, handle));
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return PP_OK_COMPLETIONPENDING;
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : raw_handle_(file_handle) {
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool FileIOResource::FileHandleHolder::IsValid(
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<FileIOResource::FileHandleHolder>& handle) {
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return handle && (handle->raw_handle() != base::kInvalidPlatformFileValue);
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::FileHandleHolder::~FileHandleHolder() {
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (raw_handle_ != base::kInvalidPlatformFileValue) {
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TaskRunner* file_task_runner =
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        PpapiGlobals::Get()->GetFileTaskRunner();
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_task_runner->PostTask(FROM_HERE,
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               base::Bind(&DoClose, raw_handle_));
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadValidated(int64_t offset,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int32_t bytes_to_read,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const PP_ArrayOutput& array_output,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      scoped_refptr<TrackedCallback> callback) {
323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (bytes_to_read < 0)
324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!FileHandleHolder::IsValid(file_handle_))
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (callback->is_blocking()) {
3321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    char* buffer = static_cast<char*>(
3331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1));
3341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int32_t result = PP_ERROR_FAILED;
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The plugin could release its reference to this instance when we release
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // the proxy lock below.
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<FileIOResource> protect(this);
3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (buffer) {
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Release the proxy lock while making a potentially slow file call.
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ProxyAutoUnlock unlock;
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      result = base::ReadPlatformFile(
3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          file_handle_->raw_handle(), offset, buffer, bytes_to_read);
3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (result < 0)
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        result = PP_ERROR_FAILED;
345ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    state_manager_.SetOperationFinished();
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return result;
348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // For the non-blocking case, post a task to the file thread.
3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<ReadOp> read_op(
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ReadOp(file_handle_, offset, bytes_to_read));
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::PostTaskAndReplyWithResult(
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      PpapiGlobals::Get()->GetFileTaskRunner(),
355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::ReadOp::DoWork, read_op),
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  callback->set_completion_task(
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        PP_FileInfo* info,
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        int32_t result) {
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(state_manager_.get_pending_operation() ==
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         FileIOStateManager::OPERATION_EXCLUSIVE);
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result == PP_OK) {
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // This writes the file info into the plugin's PP_FileInfo struct.
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(),
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            file_system_type_,
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            info);
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetOperationFinished();
377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return result;
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       PP_ArrayOutput array_output,
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       int32_t result) {
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(state_manager_.get_pending_operation() ==
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         FileIOStateManager::OPERATION_READ);
385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result >= 0) {
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ArrayWriter output;
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output.set_pp_array_output(array_output);
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (output.is_valid())
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      output.StoreArray(read_op->buffer(), result);
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      result = PP_ERROR_FAILED;
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // The read operation failed.
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = PP_ERROR_FAILED;
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetOperationFinished();
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return result;
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgGeneralComplete(
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE ||
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         state_manager_.get_pending_operation() ==
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_WRITE);
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetOperationFinished();
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback->Run(params.result());
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgOpenFileComplete(
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE);
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Release the FileRef resource.
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  file_ref_ = NULL;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params.result() == PP_OK)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    state_manager_.SetOpenSucceed();
423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t result = params.result();
425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IPC::PlatformFileForTransit transit_file;
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file)) {
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_handle_ = new FileHandleHolder(
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        IPC::PlatformFileForTransitToPlatformFile(transit_file));
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetOperationFinished();
433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback->Run(result);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_FileHandle* output_handle,
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE);
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!TrackedCallback::IsPending(callback)) {
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_manager_.SetOperationFinished();
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t result = params.result();
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC::PlatformFileForTransit transit_file;
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.TakeFileHandleAtIndex(0, &transit_file))
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result = PP_ERROR_FAILED;
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_manager_.SetOperationFinished();
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback->Run(result);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace proxy
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace ppapi
462