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