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_external_file_ref_backend.h"
6
7#include "base/files/file_path.h"
8#include "base/files/file_util_proxy.h"
9#include "content/browser/child_process_security_policy_impl.h"
10#include "content/public/browser/browser_thread.h"
11#include "ppapi/c/pp_errors.h"
12#include "ppapi/c/pp_time.h"
13#include "ppapi/host/ppapi_host.h"
14#include "ppapi/proxy/ppapi_messages.h"
15#include "ppapi/shared_impl/file_type_conversion.h"
16#include "ppapi/shared_impl/time_conversion.h"
17
18namespace content {
19
20PepperExternalFileRefBackend::PepperExternalFileRefBackend(
21    ppapi::host::PpapiHost* host,
22    int render_process_id,
23    const base::FilePath& path)
24    : host_(host),
25      path_(path),
26      render_process_id_(render_process_id),
27      weak_factory_(this) {
28  task_runner_ =
29      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
30}
31
32PepperExternalFileRefBackend::~PepperExternalFileRefBackend() {}
33
34int32_t PepperExternalFileRefBackend::MakeDirectory(
35    ppapi::host::ReplyMessageContext reply_context,
36    int32_t make_directory_flags) {
37  // This operation isn't supported for external filesystems.
38  return PP_ERROR_NOACCESS;
39}
40
41int32_t PepperExternalFileRefBackend::Touch(
42    ppapi::host::ReplyMessageContext reply_context,
43    PP_Time last_access_time,
44    PP_Time last_modified_time) {
45  IPC::Message reply_msg = PpapiPluginMsg_FileRef_TouchReply();
46  base::FileUtilProxy::Touch(
47      task_runner_.get(),
48      path_,
49      ppapi::PPTimeToTime(last_access_time),
50      ppapi::PPTimeToTime(last_modified_time),
51      base::Bind(&PepperExternalFileRefBackend::DidFinish,
52                 weak_factory_.GetWeakPtr(),
53                 reply_context,
54                 reply_msg));
55  return PP_OK_COMPLETIONPENDING;
56}
57
58int32_t PepperExternalFileRefBackend::Delete(
59    ppapi::host::ReplyMessageContext reply_context) {
60  // This operation isn't supported for external filesystems.
61  return PP_ERROR_NOACCESS;
62}
63
64int32_t PepperExternalFileRefBackend::Rename(
65    ppapi::host::ReplyMessageContext reply_context,
66    PepperFileRefHost* new_file_ref) {
67  // This operation isn't supported for external filesystems.
68  return PP_ERROR_NOACCESS;
69}
70
71int32_t PepperExternalFileRefBackend::Query(
72    ppapi::host::ReplyMessageContext reply_context) {
73  bool ok = base::FileUtilProxy::GetFileInfo(
74      task_runner_.get(),
75      path_,
76      base::Bind(&PepperExternalFileRefBackend::GetMetadataComplete,
77                 weak_factory_.GetWeakPtr(),
78                 reply_context));
79  DCHECK(ok);
80  return PP_OK_COMPLETIONPENDING;
81}
82
83int32_t PepperExternalFileRefBackend::ReadDirectoryEntries(
84    ppapi::host::ReplyMessageContext context) {
85  // This operation isn't supported for external filesystems.
86  return PP_ERROR_NOACCESS;
87}
88
89int32_t PepperExternalFileRefBackend::GetAbsolutePath(
90    ppapi::host::ReplyMessageContext reply_context) {
91  host_->SendReply(
92      reply_context,
93      PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_.AsUTF8Unsafe()));
94
95  // Use PP_OK_COMPLETIONPENDING instead of PP_OK since we've already sent our
96  // reply above.
97  return PP_OK_COMPLETIONPENDING;
98}
99
100storage::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
101  return storage::FileSystemURL();
102}
103
104base::FilePath PepperExternalFileRefBackend::GetExternalFilePath() const {
105  return path_;
106}
107
108int32_t PepperExternalFileRefBackend::CanRead() const {
109  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFile(
110          render_process_id_, path_)) {
111    return PP_ERROR_NOACCESS;
112  }
113  return PP_OK;
114}
115
116int32_t PepperExternalFileRefBackend::CanWrite() const {
117  // Platform files have coarse-grained grants in ChildProcessSecurityPolicy.
118  return CanReadWrite();
119}
120
121int32_t PepperExternalFileRefBackend::CanCreate() const {
122  // Platform files have coarse-grained grants in ChildProcessSecurityPolicy.
123  return CanReadWrite();
124}
125
126int32_t PepperExternalFileRefBackend::CanReadWrite() const {
127  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanCreateReadWriteFile(
128          render_process_id_, path_)) {
129    return PP_ERROR_NOACCESS;
130  }
131  return PP_OK;
132}
133
134void PepperExternalFileRefBackend::DidFinish(
135    ppapi::host::ReplyMessageContext reply_context,
136    const IPC::Message& msg,
137    base::File::Error error) {
138  reply_context.params.set_result(ppapi::FileErrorToPepperError(error));
139  host_->SendReply(reply_context, msg);
140}
141
142void PepperExternalFileRefBackend::GetMetadataComplete(
143    ppapi::host::ReplyMessageContext reply_context,
144    const base::File::Error error,
145    const base::File::Info& file_info) {
146  reply_context.params.set_result(ppapi::FileErrorToPepperError(error));
147
148  PP_FileInfo pp_file_info;
149  if (error == base::File::FILE_OK) {
150    ppapi::FileInfoToPepperFileInfo(
151        file_info, PP_FILESYSTEMTYPE_EXTERNAL, &pp_file_info);
152  } else {
153    memset(&pp_file_info, 0, sizeof(pp_file_info));
154  }
155
156  host_->SendReply(reply_context,
157                   PpapiPluginMsg_FileRef_QueryReply(pp_file_info));
158}
159
160}  // namespace content
161