[M108 Aura Migration][NaCl][PPFwk] Add error logs + SVACE/DLOG/Static analysis fix
[platform/framework/web/chromium-efl.git] / content / browser / renderer_host / pepper / pepper_file_io_host.cc
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/logging.h"
12 #include "base/callback_forward.h"
13 #include "base/callback_helpers.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "base/task/thread_pool.h"
17 #include "build/build_config.h"
18 #include "content/browser/renderer_host/pepper/pepper_file_ref_host.h"
19 #include "content/browser/renderer_host/pepper/pepper_file_system_browser_host.h"
20 #include "content/browser/renderer_host/pepper/pepper_security_helper.h"
21 #include "content/public/browser/browser_task_traits.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/content_browser_client.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/storage_partition.h"
26 #include "content/public/common/content_client.h"
27 #include "ipc/ipc_platform_file.h"
28 #include "mojo/public/cpp/bindings/callback_helpers.h"
29 #include "ppapi/c/pp_errors.h"
30 #include "ppapi/c/ppb_file_io.h"
31 #include "ppapi/host/dispatch_host_message.h"
32 #include "ppapi/host/ppapi_host.h"
33 #include "ppapi/proxy/ppapi_messages.h"
34 #include "ppapi/shared_impl/file_system_util.h"
35 #include "ppapi/shared_impl/file_type_conversion.h"
36 #include "ppapi/shared_impl/time_conversion.h"
37 #include "storage/browser/file_system/file_observers.h"
38 #include "storage/browser/file_system/file_system_context.h"
39 #include "storage/browser/file_system/file_system_operation_runner.h"
40 #include "storage/browser/file_system/task_runner_bound_observer_list.h"
41 #include "storage/common/file_system/file_system_util.h"
42
43 namespace content {
44
45 using ppapi::FileIOStateManager;
46 using ppapi::PPTimeToTime;
47
48 namespace {
49
50 PepperFileIOHost::UIThreadStuff GetUIThreadStuffForInternalFileSystems(
51     int render_process_id) {
52   PepperFileIOHost::UIThreadStuff stuff;
53   DCHECK_CURRENTLY_ON(BrowserThread::UI);
54   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
55   if (host) {
56     stuff.resolved_render_process_id = host->GetProcess().Pid();
57     StoragePartition* storage_partition = host->GetStoragePartition();
58     if (storage_partition)
59       stuff.file_system_context = storage_partition->GetFileSystemContext();
60   }
61   return stuff;
62 }
63
64 base::ProcessId GetResolvedRenderProcessId(int render_process_id) {
65   DCHECK_CURRENTLY_ON(BrowserThread::UI);
66   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
67   if (!host)
68     return base::kNullProcessId;
69   return host->GetProcess().Pid();
70 }
71
72 bool GetPluginAllowedToCallRequestOSFileHandle(int render_process_id,
73                                                const GURL& document_url) {
74   DCHECK_CURRENTLY_ON(BrowserThread::UI);
75   ContentBrowserClient* client = GetContentClient()->browser();
76   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
77   if (!host)
78     return false;
79   return client->IsPluginAllowedToCallRequestOSFileHandle(
80       host->GetBrowserContext(), document_url);
81 }
82
83 bool FileOpenForWrite(int32_t open_flags) {
84   return (open_flags & (PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND)) != 0;
85 }
86
87 void FileCloser(base::File auto_close) {
88 }
89
90 void DidCloseFile(base::ScopedClosureRunner on_close_callback) {
91   on_close_callback.RunAndReset();
92 }
93
94 void DidOpenFile(base::WeakPtr<PepperFileIOHost> file_host,
95                  scoped_refptr<base::SequencedTaskRunner> task_runner,
96                  storage::FileSystemOperation::OpenFileCallback callback,
97                  base::File file,
98                  base::ScopedClosureRunner on_close_callback) {
99   if (file_host) {
100     std::move(callback).Run(std::move(file), on_close_callback.Release());
101   } else {
102     task_runner->PostTaskAndReply(
103         FROM_HERE, base::BindOnce(&FileCloser, std::move(file)),
104         base::BindOnce(&DidCloseFile, std::move(on_close_callback)));
105   }
106 }
107
108 void OpenFileCallbackWrapperIO(
109     storage::FileSystemOperationRunner::OpenFileCallback callback,
110     base::File file,
111     base::ScopedClosureRunner on_close_callback) {
112   GetUIThreadTaskRunner({})->PostTask(
113       FROM_HERE, base::BindOnce(std::move(callback), std::move(file),
114                                 std::move(on_close_callback)));
115 }
116
117 void CallOpenFile(
118     PepperFileSystemBrowserHost::GetOperationRunnerCallback get_runner,
119     const storage::FileSystemURL& url,
120     uint32_t file_flags,
121     storage::FileSystemOperationRunner::OpenFileCallback callback) {
122   get_runner.Run()->OpenFile(
123       url, file_flags,
124       base::BindOnce(&OpenFileCallbackWrapperIO, std::move(callback)));
125 }
126
127 }  // namespace
128
129 PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host,
130                                    PP_Instance instance,
131                                    PP_Resource resource)
132     : ResourceHost(host->GetPpapiHost(), instance, resource),
133       browser_ppapi_host_(host),
134       task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
135           {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
136            base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
137       file_(task_runner_.get()),
138       resolved_render_process_id_(base::kNullProcessId),
139       open_flags_(0),
140       file_system_type_(PP_FILESYSTEMTYPE_INVALID),
141       max_written_offset_(0),
142       check_quota_(false) {
143   int unused;
144   if (!host->GetRenderFrameIDsForInstance(
145           instance, &render_process_id_, &unused)) {
146     render_process_id_ = -1;
147   }
148 }
149
150 PepperFileIOHost::~PepperFileIOHost() {}
151
152 int32_t PepperFileIOHost::OnResourceMessageReceived(
153     const IPC::Message& msg,
154     ppapi::host::HostMessageContext* context) {
155   PPAPI_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
156     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open, OnHostMsgOpen)
157     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch, OnHostMsgTouch)
158     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
159                                       OnHostMsgSetLength)
160     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Flush,
161                                         OnHostMsgFlush)
162     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Close, OnHostMsgClose)
163     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_RequestOSFileHandle,
164                                         OnHostMsgRequestOSFileHandle)
165   PPAPI_END_MESSAGE_MAP()
166   LOG(ERROR) << "Message not resolved";
167   return PP_ERROR_FAILED;
168 }
169
170 PepperFileIOHost::UIThreadStuff::UIThreadStuff() {
171   resolved_render_process_id = base::kNullProcessId;
172 }
173
174 PepperFileIOHost::UIThreadStuff::UIThreadStuff(const UIThreadStuff& other) =
175     default;
176
177 PepperFileIOHost::UIThreadStuff::~UIThreadStuff() {}
178
179 int32_t PepperFileIOHost::OnHostMsgOpen(
180     ppapi::host::HostMessageContext* context,
181     PP_Resource file_ref_resource,
182     int32_t open_flags) {
183   int32_t rv = state_manager_.CheckOperationState(
184       FileIOStateManager::OPERATION_EXCLUSIVE, false);
185   if (rv != PP_OK)
186     return rv;
187
188   uint32_t platform_file_flags = 0;
189   if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
190                                                      &platform_file_flags)) {
191     LOG(ERROR);
192     return PP_ERROR_BADARGUMENT;
193   }
194
195   ppapi::host::ResourceHost* resource_host =
196       host()->GetResourceHost(file_ref_resource);
197   if (!resource_host || !resource_host->IsFileRefHost()) {
198     LOG(ERROR) << "Invalid Resource";
199     return PP_ERROR_BADRESOURCE;
200   }
201   PepperFileRefHost* file_ref_host =
202       static_cast<PepperFileRefHost*>(resource_host);
203   if (file_ref_host->GetFileSystemType() == PP_FILESYSTEMTYPE_INVALID) {
204     LOG(ERROR) << "Invalid FileSystem type";
205     return PP_ERROR_FAILED;
206   }
207
208   file_system_host_ = file_ref_host->GetFileSystemHost();
209
210   open_flags_ = open_flags;
211   file_system_type_ = file_ref_host->GetFileSystemType();
212   file_system_url_ = file_ref_host->GetFileSystemURL();
213
214   // For external file systems, if there is a valid FileSystemURL, then treat
215   // it like internal file systems and access it via the FileSystemURL.
216   bool is_internal_type = (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) ||
217                           file_system_url_.is_valid();
218
219   if (is_internal_type) {
220     if (!file_system_url_.is_valid()) {
221       LOG(ERROR) << "Invalid URL";
222       return PP_ERROR_BADARGUMENT;
223     }
224
225     // Not all external file systems are fully supported yet.
226     // Whitelist the supported ones.
227     if (file_system_url_.mount_type() == storage::kFileSystemTypeExternal) {
228       switch (file_system_url_.type()) {
229         case storage::kFileSystemTypeLocalMedia:
230         case storage::kFileSystemTypeDeviceMedia:
231           break;
232         default:
233           LOG(ERROR) << "External file system of type "
234                      << file_system_url_.type() << " not supported";
235           return PP_ERROR_NOACCESS;
236       }
237     }
238     if (!CanOpenFileSystemURLWithPepperFlags(open_flags, render_process_id_,
239                                              file_system_url_)) {
240       LOG(ERROR) << "Cannot open file system URL with pepper flags";
241       return PP_ERROR_NOACCESS;
242     }
243
244     GotUIThreadStuffForInternalFileSystems(
245         context->MakeReplyMessageContext(), platform_file_flags,
246         GetUIThreadStuffForInternalFileSystems(render_process_id_));
247   } else {
248     base::FilePath path = file_ref_host->GetExternalFilePath();
249     if (!CanOpenWithPepperFlags(open_flags, render_process_id_, path)) {
250       LOG(ERROR) << "Cannot open with pepper flags";
251       return PP_ERROR_NOACCESS;
252     }
253     GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
254         FROM_HERE,
255         base::BindOnce(&GetResolvedRenderProcessId, render_process_id_),
256         base::BindOnce(&PepperFileIOHost::GotResolvedRenderProcessId,
257                        AsWeakPtr(), context->MakeReplyMessageContext(), path,
258                        platform_file_flags));
259   }
260   state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
261   return PP_OK_COMPLETIONPENDING;
262 }
263
264 void PepperFileIOHost::GotUIThreadStuffForInternalFileSystems(
265     ppapi::host::ReplyMessageContext reply_context,
266     uint32_t platform_file_flags,
267     UIThreadStuff ui_thread_stuff) {
268   DCHECK_CURRENTLY_ON(BrowserThread::UI);
269   resolved_render_process_id_ = ui_thread_stuff.resolved_render_process_id;
270   if (resolved_render_process_id_ == base::kNullProcessId ||
271       !ui_thread_stuff.file_system_context.get()) {
272     reply_context.params.set_result(PP_ERROR_FAILED);
273     SendOpenErrorReply(reply_context);
274     return;
275   }
276
277   if (!ui_thread_stuff.file_system_context->GetFileSystemBackend(
278           file_system_url_.type())) {
279     reply_context.params.set_result(PP_ERROR_FAILED);
280     SendOpenErrorReply(reply_context);
281     return;
282   }
283
284   if (!file_system_host_.get()) {
285     reply_context.params.set_result(PP_ERROR_FAILED);
286     SendOpenErrorReply(reply_context);
287     return;
288   }
289
290   auto open_callback =
291       base::BindOnce(&DidOpenFile, AsWeakPtr(), task_runner_,
292                      base::BindOnce(&PepperFileIOHost::DidOpenInternalFile,
293                                     AsWeakPtr(), reply_context));
294   GetIOThreadTaskRunner({})->PostTask(
295       FROM_HERE,
296       base::BindOnce(
297           CallOpenFile, file_system_host_->GetFileSystemOperationRunner(),
298           file_system_url_, platform_file_flags, std::move(open_callback)));
299 }
300
301 void PepperFileIOHost::DidOpenInternalFile(
302     ppapi::host::ReplyMessageContext reply_context,
303     base::File file,
304     base::OnceClosure on_close_callback) {
305   if (file.IsValid()) {
306     base::ScopedClosureRunner scoped_runner(std::move(on_close_callback));
307     on_close_callback_ = std::move(scoped_runner);
308
309     if (FileOpenForWrite(open_flags_) && file_system_host_->ChecksQuota()) {
310       check_quota_ = true;
311       file_system_host_->OpenQuotaFile(
312           this, file_system_url_,
313           base::BindOnce(&PepperFileIOHost::DidOpenQuotaFile, AsWeakPtr(),
314                          reply_context, std::move(file)));
315       return;
316     }
317   }
318
319   DCHECK(!file_.IsValid());
320   base::File::Error error =
321       file.IsValid() ? base::File::FILE_OK : file.error_details();
322   file_.SetFile(std::move(file));
323   SendFileOpenReply(reply_context, error);
324 }
325
326 void PepperFileIOHost::GotResolvedRenderProcessId(
327     ppapi::host::ReplyMessageContext reply_context,
328     base::FilePath path,
329     uint32_t file_flags,
330     base::ProcessId resolved_render_process_id) {
331   DCHECK_CURRENTLY_ON(BrowserThread::UI);
332   resolved_render_process_id_ = resolved_render_process_id;
333   file_.CreateOrOpen(path, file_flags,
334                      base::BindOnce(&PepperFileIOHost::OnLocalFileOpened,
335                                     AsWeakPtr(), reply_context, path));
336 }
337
338 int32_t PepperFileIOHost::OnHostMsgTouch(
339     ppapi::host::HostMessageContext* context,
340     PP_Time last_access_time,
341     PP_Time last_modified_time) {
342   int32_t rv = state_manager_.CheckOperationState(
343       FileIOStateManager::OPERATION_EXCLUSIVE, true);
344   if (rv != PP_OK)
345     return rv;
346
347   if (!file_.SetTimes(
348           PPTimeToTime(last_access_time), PPTimeToTime(last_modified_time),
349           base::BindOnce(&PepperFileIOHost::ExecutePlatformGeneralCallback,
350                          AsWeakPtr(), context->MakeReplyMessageContext()))) {
351     LOG(ERROR) << "Could not modify file access and modification times";
352     return PP_ERROR_FAILED;
353   }
354
355   state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
356   return PP_OK_COMPLETIONPENDING;
357 }
358
359 int32_t PepperFileIOHost::OnHostMsgSetLength(
360     ppapi::host::HostMessageContext* context,
361     int64_t length) {
362   int32_t rv = state_manager_.CheckOperationState(
363       FileIOStateManager::OPERATION_EXCLUSIVE, true);
364   if (rv != PP_OK)
365     return rv;
366   if (length < 0) {
367     LOG(ERROR) << "New length cannot be less than 0, length=" << length;
368     return PP_ERROR_BADARGUMENT;
369   }
370
371   // Quota checks are performed on the plugin side, in order to use the same
372   // quota reservation and request system as Write.
373
374   if (!file_.SetLength(
375           length,
376           base::BindOnce(&PepperFileIOHost::ExecutePlatformGeneralCallback,
377                          AsWeakPtr(), context->MakeReplyMessageContext()))) {
378     LOG(ERROR) << "SetLength failed";
379     return PP_ERROR_FAILED;
380   }
381
382   state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
383   return PP_OK_COMPLETIONPENDING;
384 }
385
386 int32_t PepperFileIOHost::OnHostMsgFlush(
387     ppapi::host::HostMessageContext* context) {
388   int32_t rv = state_manager_.CheckOperationState(
389       FileIOStateManager::OPERATION_EXCLUSIVE, true);
390   if (rv != PP_OK)
391     return rv;
392
393   if (!file_.Flush(
394           base::BindOnce(&PepperFileIOHost::ExecutePlatformGeneralCallback,
395                          AsWeakPtr(), context->MakeReplyMessageContext()))) {
396     LOG(ERROR) << "Flush failed";
397     return PP_ERROR_FAILED;
398   }
399
400   state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
401   return PP_OK_COMPLETIONPENDING;
402 }
403
404 int32_t PepperFileIOHost::OnHostMsgClose(
405     ppapi::host::HostMessageContext* context,
406     const ppapi::FileGrowth& file_growth) {
407   if (check_quota_) {
408     file_system_host_->CloseQuotaFile(this, file_growth);
409     check_quota_ = false;
410   }
411
412   if (file_.IsValid()) {
413     file_.Close(base::BindOnce(&PepperFileIOHost::DidCloseFile, AsWeakPtr()));
414   }
415   return PP_OK;
416 }
417
418 void PepperFileIOHost::DidOpenQuotaFile(
419     ppapi::host::ReplyMessageContext reply_context,
420     base::File file,
421     int64_t max_written_offset) {
422   DCHECK(!file_.IsValid());
423   DCHECK(file.IsValid());
424   max_written_offset_ = max_written_offset;
425   file_.SetFile(std::move(file));
426
427   SendFileOpenReply(reply_context, base::File::FILE_OK);
428 }
429
430 void PepperFileIOHost::DidCloseFile(base::File::Error /*error*/) {
431   // Silently ignore if we fail to close the file.
432   on_close_callback_.RunAndReset();
433 }
434
435 int32_t PepperFileIOHost::OnHostMsgRequestOSFileHandle(
436     ppapi::host::HostMessageContext* context) {
437   if (open_flags_ != PP_FILEOPENFLAG_READ && file_system_host_->ChecksQuota()) {
438     LOG(ERROR);
439     return PP_ERROR_FAILED;
440   }
441
442   GURL document_url =
443       browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
444   GetUIThreadTaskRunner({})->PostTaskAndReplyWithResult(
445       FROM_HERE,
446       base::BindOnce(&GetPluginAllowedToCallRequestOSFileHandle,
447                      render_process_id_, document_url),
448       base::BindOnce(
449           &PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle,
450           AsWeakPtr(), context->MakeReplyMessageContext()));
451   return PP_OK_COMPLETIONPENDING;
452 }
453
454 void PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle(
455     ppapi::host::ReplyMessageContext reply_context,
456     bool plugin_allowed) {
457   DCHECK_CURRENTLY_ON(BrowserThread::UI);
458   if (!browser_ppapi_host_->external_plugin() ||
459       host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) ||
460       plugin_allowed) {
461     if (!AddFileToReplyContext(open_flags_, &reply_context))
462       reply_context.params.set_result(PP_ERROR_FAILED);
463   } else {
464     reply_context.params.set_result(PP_ERROR_NOACCESS);
465   }
466   host()->SendReply(reply_context,
467                     PpapiPluginMsg_FileIO_RequestOSFileHandleReply());
468 }
469
470 void PepperFileIOHost::ExecutePlatformGeneralCallback(
471     ppapi::host::ReplyMessageContext reply_context,
472     base::File::Error error_code) {
473   reply_context.params.set_result(ppapi::FileErrorToPepperError(error_code));
474   host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
475   state_manager_.SetOperationFinished();
476 }
477
478 void PepperFileIOHost::OnLocalFileOpened(
479     ppapi::host::ReplyMessageContext reply_context,
480     const base::FilePath& path,
481     base::File::Error error_code) {
482 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
483   // Quarantining a file before its contents are available is only supported on
484   // Windows and Linux.
485   if (!FileOpenForWrite(open_flags_) || error_code != base::File::FILE_OK) {
486     SendFileOpenReply(reply_context, error_code);
487     return;
488   }
489
490   mojo::Remote<quarantine::mojom::Quarantine> quarantine_remote;
491   download::QuarantineConnectionCallback quarantine_connection_callback =
492       GetContentClient()->browser()->GetQuarantineConnectionCallback();
493   if (quarantine_connection_callback) {
494     quarantine_connection_callback.Run(
495         quarantine_remote.BindNewPipeAndPassReceiver());
496   }
497
498   if (quarantine_remote) {
499     quarantine::mojom::Quarantine* raw_quarantine = quarantine_remote.get();
500     raw_quarantine->QuarantineFile(
501         path, browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()),
502         GURL(), std::string(),
503         mojo::WrapCallbackWithDefaultInvokeIfNotRun(
504             base::BindOnce(&PepperFileIOHost::OnLocalFileQuarantined,
505                            AsWeakPtr(), reply_context, path,
506                            std::move(quarantine_remote)),
507             quarantine::mojom::QuarantineFileResult::ANNOTATION_FAILED));
508   } else {
509     SendFileOpenReply(reply_context, error_code);
510   }
511 #else
512   SendFileOpenReply(reply_context, error_code);
513 #endif
514 }
515
516 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
517 void PepperFileIOHost::OnLocalFileQuarantined(
518     ppapi::host::ReplyMessageContext reply_context,
519     const base::FilePath& path,
520     mojo::Remote<quarantine::mojom::Quarantine> quarantine_remote,
521     quarantine::mojom::QuarantineFileResult quarantine_result) {
522   base::File::Error file_error =
523       (quarantine_result == quarantine::mojom::QuarantineFileResult::OK
524            ? base::File::FILE_OK
525            : base::File::FILE_ERROR_SECURITY);
526   if (file_error != base::File::FILE_OK && file_.IsValid())
527     file_.Close(base::FileProxy::StatusCallback());
528   SendFileOpenReply(reply_context, file_error);
529 }
530 #endif
531
532 void PepperFileIOHost::SendFileOpenReply(
533     ppapi::host::ReplyMessageContext reply_context,
534     base::File::Error error_code) {
535   int32_t pp_error = ppapi::FileErrorToPepperError(error_code);
536   if (file_.IsValid() && !AddFileToReplyContext(open_flags_, &reply_context))
537     pp_error = PP_ERROR_FAILED;
538
539   PP_Resource quota_file_system = 0;
540   if (pp_error == PP_OK) {
541     state_manager_.SetOpenSucceed();
542     // A non-zero resource id signals the plugin side to check quota.
543     if (check_quota_)
544       quota_file_system = file_system_host_->pp_resource();
545   }
546
547   reply_context.params.set_result(pp_error);
548   host()->SendReply(
549       reply_context,
550       PpapiPluginMsg_FileIO_OpenReply(quota_file_system, max_written_offset_));
551   state_manager_.SetOperationFinished();
552 }
553
554 void PepperFileIOHost::SendOpenErrorReply(
555     ppapi::host::ReplyMessageContext reply_context) {
556   host()->SendReply(reply_context, PpapiPluginMsg_FileIO_OpenReply(0, 0));
557 }
558
559 bool PepperFileIOHost::AddFileToReplyContext(
560     int32_t open_flags,
561     ppapi::host::ReplyMessageContext* reply_context) const {
562   IPC::PlatformFileForTransit transit_file =
563       IPC::GetPlatformFileForTransit(file_.GetPlatformFile(), false);
564   if (transit_file == IPC::InvalidPlatformFileForTransit())
565     return false;
566
567   ppapi::proxy::SerializedHandle file_handle;
568   // A non-zero resource id signals NaClIPCAdapter to create a NaClQuotaDesc.
569   PP_Resource quota_file_io = check_quota_ ? pp_resource() : 0;
570   file_handle.set_file_handle(transit_file, open_flags, quota_file_io);
571   reply_context->params.AppendHandle(std::move(file_handle));
572   return true;
573 }
574
575 }  // namespace content