file_io_resource.cc revision f2477e01787aa58f445919b809d89e252beef54f
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"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/shared_impl/file_ref_create_info.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ppapi/shared_impl/file_system_util.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/file_type_conversion.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ppapi/shared_impl/proxy_lock.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/enter.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/thunk/ppb_file_ref_api.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileIO_API;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ppapi::thunk::PPB_FileRef_API;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// We must allocate a buffer sized according to the request of the plugin. To
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// reduce the chance of out-of-memory errors, we cap the read size to 32MB.
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// This is OK since the API specifies that it may perform a partial read.
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const int32_t kMaxReadSize = 32 * 1024 * 1024;  // 32MB
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An adapter to let Read() share the same implementation with ReadToArray().
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return user_data;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// File thread task to close the file handle.
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid DoClose(base::PlatformFile file) {
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::ClosePlatformFile(file);
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ppapi {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace proxy {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::QueryOp::QueryOp(scoped_refptr<FileHandleHolder> file_handle)
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : file_handle_(file_handle) {
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(file_handle_);
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::QueryOp::~QueryOp() {
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::QueryOp::DoWork() {
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info_) ?
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      PP_OK : PP_ERROR_FAILED;
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::ReadOp::ReadOp(scoped_refptr<FileHandleHolder> file_handle,
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                               int64_t offset,
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                               int32_t bytes_to_read)
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  : file_handle_(file_handle),
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    offset_(offset),
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bytes_to_read_(bytes_to_read) {
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(file_handle_);
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochFileIOResource::ReadOp::~ReadOp() {
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::ReadOp::DoWork() {
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(!buffer_.get());
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  buffer_.reset(new char[bytes_to_read_]);
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return base::ReadPlatformFile(
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      file_handle_->raw_handle(), offset_, buffer_.get(), bytes_to_read_);
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : PluginResource(connection, instance),
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      file_system_type_(PP_FILESYSTEMTYPE_INVALID) {
830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  SendCreate(BROWSER, PpapiHostMsg_FileIO_Create());
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FileIOResource::~FileIOResource() {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return this;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Open(PP_Resource file_ref,
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int32_t open_flags,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             scoped_refptr<TrackedCallback> callback) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, true);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enter.failed())
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return PP_ERROR_BADRESOURCE;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  PPB_FileRef_API* file_ref_api = enter.object();
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const FileRefCreateInfo& create_info = file_ref_api->GetCreateInfo();
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!FileSystemTypeIsValid(create_info.file_system_type)) {
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    NOTREACHED();
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, false);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_system_type_ = create_info.file_system_type;
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Keep the FileSystem host alive by taking a reference to its resource. The
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // FileIO host uses the FileSystem host for running tasks.
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  file_system_resource_ = create_info.file_system_plugin_resource;
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Take a reference on the FileRef resource while we're opening the file; we
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // don't want the plugin destroying it during the Open operation.
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  file_ref_ = enter.resource();
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_OpenReply>(BROWSER,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Open(
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          file_ref,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          open_flags),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Query(PP_FileInfo* info,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!info)
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_BADARGUMENT;
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!FileHandleHolder::IsValid(file_handle_))
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If the callback is blocking, perform the task on the calling thread.
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (callback->is_blocking()) {
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int32_t result = PP_ERROR_FAILED;
1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::PlatformFileInfo file_info;
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The plugin could release its reference to this instance when we release
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // the proxy lock below.
1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<FileIOResource> protect(this);
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    {
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Release the proxy lock while making a potentially slow file call.
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ProxyAutoUnlock unlock;
1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (base::GetPlatformFileInfo(file_handle_->raw_handle(), &file_info))
1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        result = PP_OK;
1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (result == PP_OK) {
1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // This writes the file info into the plugin's PP_FileInfo struct.
1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      ppapi::PlatformFileInfoToPepperFileInfo(file_info,
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              file_system_type_,
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                              info);
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    state_manager_.SetOperationFinished();
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return result;
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // For the non-blocking case, post a task to the file thread and add a
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // completion task to write the result.
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_));
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::PostTaskAndReplyWithResult(
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      PpapiGlobals::Get()->GetFileTaskRunner(),
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::QueryOp::DoWork, query_op),
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  callback->set_completion_task(
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Touch(PP_Time last_access_time,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              PP_Time last_modified_time,
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Touch(last_access_time, last_modified_time),
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Read(int64_t offset,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             char* buffer,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int32_t bytes_to_read,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             scoped_refptr<TrackedCallback> callback) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_READ, true);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_ArrayOutput output_adapter;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_adapter.GetDataBuffer = &DummyGetDataBuffer;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_adapter.user_data = buffer;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ReadValidated(offset, bytes_to_read, output_adapter, callback);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadToArray(int64_t offset,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    int32_t max_read_length,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    PP_ArrayOutput* array_output,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    scoped_refptr<TrackedCallback> callback) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(array_output);
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_READ, true);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ReadValidated(offset, max_read_length, *array_output, callback);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Write(int64_t offset,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const char* buffer,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              int32_t bytes_to_write,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              scoped_refptr<TrackedCallback> callback) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_WRITE, true);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(brettw) it would be nice to use a shared memory buffer for large
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // writes rather than having to copy to a string (which will involve a number
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // of extra copies to serialize over IPC).
2390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Write(offset, std::string(buffer, bytes_to_write)),
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_WRITE);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::SetLength(int64_t length,
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  scoped_refptr<TrackedCallback> callback) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_SetLength(length),
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::Flush(scoped_refptr<TrackedCallback> callback) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t rv = state_manager_.CheckOperationState(
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FileIOStateManager::OPERATION_EXCLUSIVE, true);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != PP_OK)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_GeneralReply>(BROWSER,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PpapiHostMsg_FileIO_Flush(),
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 callback));
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::Close() {
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (file_handle_) {
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_handle_ = NULL;
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Post(BROWSER, PpapiHostMsg_FileIO_Close());
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::RequestOSFileHandle(
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    PP_FileHandle* handle,
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_refptr<TrackedCallback> callback) {
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int32_t rv = state_manager_.CheckOperationState(
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FileIOStateManager::OPERATION_EXCLUSIVE, true);
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (rv != PP_OK)
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return rv;
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  Call<PpapiPluginMsg_FileIO_RequestOSFileHandleReply>(BROWSER,
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      PpapiHostMsg_FileIO_RequestOSFileHandle(),
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Bind(&FileIOResource::OnPluginMsgRequestOSFileHandleComplete, this,
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                 callback, handle));
298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return PP_OK_COMPLETIONPENDING;
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::FileHandleHolder::FileHandleHolder(PP_FileHandle file_handle)
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : raw_handle_(file_handle) {
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool FileIOResource::FileHandleHolder::IsValid(
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<FileIOResource::FileHandleHolder>& handle) {
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return handle && (handle->raw_handle() != base::kInvalidPlatformFileValue);
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)FileIOResource::FileHandleHolder::~FileHandleHolder() {
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (raw_handle_ != base::kInvalidPlatformFileValue) {
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::TaskRunner* file_task_runner =
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        PpapiGlobals::Get()->GetFileTaskRunner();
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_task_runner->PostTask(FROM_HERE,
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               base::Bind(&DoClose, raw_handle_));
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t FileIOResource::ReadValidated(int64_t offset,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      int32_t bytes_to_read,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const PP_ArrayOutput& array_output,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      scoped_refptr<TrackedCallback> callback) {
326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (bytes_to_read < 0)
327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!FileHandleHolder::IsValid(file_handle_))
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return PP_ERROR_FAILED;
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
331ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (callback->is_blocking()) {
3351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    char* buffer = static_cast<char*>(
3361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        array_output.GetDataBuffer(array_output.user_data, bytes_to_read, 1));
3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    int32_t result = PP_ERROR_FAILED;
3381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The plugin could release its reference to this instance when we release
3391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // the proxy lock below.
3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_refptr<FileIOResource> protect(this);
3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (buffer) {
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Release the proxy lock while making a potentially slow file call.
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ProxyAutoUnlock unlock;
3441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      result = base::ReadPlatformFile(
3451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          file_handle_->raw_handle(), offset, buffer, bytes_to_read);
3461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (result < 0)
3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        result = PP_ERROR_FAILED;
348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
3491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    state_manager_.SetOperationFinished();
3501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return result;
351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // For the non-blocking case, post a task to the file thread.
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<ReadOp> read_op(
3551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ReadOp(file_handle_, offset, bytes_to_read));
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::PostTaskAndReplyWithResult(
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      PpapiGlobals::Get()->GetFileTaskRunner(),
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      FROM_HERE,
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::ReadOp::DoWork, read_op),
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  callback->set_completion_task(
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        PP_FileInfo* info,
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                        int32_t result) {
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(state_manager_.get_pending_operation() ==
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         FileIOStateManager::OPERATION_EXCLUSIVE);
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result == PP_OK) {
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // This writes the file info into the plugin's PP_FileInfo struct.
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(),
376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            file_system_type_,
377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            info);
378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetOperationFinished();
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return result;
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
383ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochint32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
384ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       PP_ArrayOutput array_output,
385ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       int32_t result) {
386ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(state_manager_.get_pending_operation() ==
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch         FileIOStateManager::OPERATION_READ);
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (result >= 0) {
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ArrayWriter output;
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    output.set_pp_array_output(array_output);
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (output.is_valid())
392ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      output.StoreArray(read_op->buffer(), result);
393ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    else
394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      result = PP_ERROR_FAILED;
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // The read operation failed.
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    result = PP_ERROR_FAILED;
398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  state_manager_.SetOperationFinished();
400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return result;
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgGeneralComplete(
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE ||
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         state_manager_.get_pending_operation() ==
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_WRITE);
410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetOperationFinished();
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback->Run(params.result());
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FileIOResource::OnPluginMsgOpenFileComplete(
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE);
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Release the FileRef resource.
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  file_ref_ = NULL;
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (params.result() == PP_OK)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    state_manager_.SetOpenSucceed();
426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t result = params.result();
428ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  IPC::PlatformFileForTransit transit_file;
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file)) {
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    file_handle_ = new FileHandleHolder(
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        IPC::PlatformFileForTransitToPlatformFile(transit_file));
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  state_manager_.SetOperationFinished();
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  callback->Run(result);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FileIOResource::OnPluginMsgRequestOSFileHandleComplete(
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_refptr<TrackedCallback> callback,
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_FileHandle* output_handle,
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceMessageReplyParams& params) {
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(state_manager_.get_pending_operation() ==
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         FileIOStateManager::OPERATION_EXCLUSIVE);
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!TrackedCallback::IsPending(callback)) {
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_manager_.SetOperationFinished();
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t result = params.result();
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC::PlatformFileForTransit transit_file;
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!params.TakeFileHandleAtIndex(0, &transit_file))
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result = PP_ERROR_FAILED;
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // End this operation now, so the user's callback can execute another FileIO
458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // operation, assuming there are no other pending operations.
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  state_manager_.SetOperationFinished();
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback->Run(result);
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace proxy
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace ppapi
465