1 // Copyright (c) 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/renderer/pepper/pepper_file_system_host.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/optional.h"
10 #include "content/common/pepper_file_util.h"
11 #include "content/public/common/service_names.mojom.h"
12 #include "content/public/renderer/render_view.h"
13 #include "content/public/renderer/renderer_ppapi_host.h"
14 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
15 #include "content/renderer/render_thread_impl.h"
16 #include "ppapi/c/pp_errors.h"
17 #include "ppapi/host/dispatch_host_message.h"
18 #include "ppapi/host/ppapi_host.h"
19 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/shared_impl/file_system_util.h"
21 #include "ppapi/shared_impl/file_type_conversion.h"
22 #include "storage/common/file_system/file_system_util.h"
23 #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
24 #include "third_party/blink/public/web/web_document.h"
25 #include "third_party/blink/public/web/web_local_frame.h"
26 #include "third_party/blink/public/web/web_view.h"
27 
28 namespace content {
29 
30 namespace {
31 
32 base::Optional<blink::mojom::FileSystemType>
PepperFileSystemTypeToMojoFileSystemType(PP_FileSystemType type)33 PepperFileSystemTypeToMojoFileSystemType(PP_FileSystemType type) {
34   switch (type) {
35     case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
36       return blink::mojom::FileSystemType::kTemporary;
37     case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
38       return blink::mojom::FileSystemType::kPersistent;
39     case PP_FILESYSTEMTYPE_EXTERNAL:
40       return blink::mojom::FileSystemType::kExternal;
41     default:
42       return base::nullopt;
43   }
44 }
45 
46 }  // namespace
47 
PepperFileSystemHost(RendererPpapiHost * host,PP_Instance instance,PP_Resource resource,PP_FileSystemType type)48 PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
49                                            PP_Instance instance,
50                                            PP_Resource resource,
51                                            PP_FileSystemType type)
52     : ResourceHost(host->GetPpapiHost(), instance, resource),
53       renderer_ppapi_host_(host),
54       type_(type),
55       opened_(false),
56       called_open_(false) {}
57 
PepperFileSystemHost(RendererPpapiHost * host,PP_Instance instance,PP_Resource resource,const GURL & root_url,PP_FileSystemType type)58 PepperFileSystemHost::PepperFileSystemHost(RendererPpapiHost* host,
59                                            PP_Instance instance,
60                                            PP_Resource resource,
61                                            const GURL& root_url,
62                                            PP_FileSystemType type)
63     : ResourceHost(host->GetPpapiHost(), instance, resource),
64       renderer_ppapi_host_(host),
65       type_(type),
66       opened_(true),
67       root_url_(root_url),
68       called_open_(true) {}
69 
~PepperFileSystemHost()70 PepperFileSystemHost::~PepperFileSystemHost() {}
71 
OnResourceMessageReceived(const IPC::Message & msg,ppapi::host::HostMessageContext * context)72 int32_t PepperFileSystemHost::OnResourceMessageReceived(
73     const IPC::Message& msg,
74     ppapi::host::HostMessageContext* context) {
75   PPAPI_BEGIN_MESSAGE_MAP(PepperFileSystemHost, msg)
76     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileSystem_Open,
77                                       OnHostMsgOpen)
78     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
79         PpapiHostMsg_FileSystem_InitIsolatedFileSystem,
80         OnHostMsgInitIsolatedFileSystem)
81   PPAPI_END_MESSAGE_MAP()
82   return PP_ERROR_FAILED;
83 }
84 
IsFileSystemHost()85 bool PepperFileSystemHost::IsFileSystemHost() { return true; }
86 
DidOpenFileSystem(const std::string &,const GURL & root,base::File::Error error)87 void PepperFileSystemHost::DidOpenFileSystem(
88     const std::string& /* name_unused */,
89     const GURL& root,
90     base::File::Error error) {
91   if (error != base::File::FILE_OK) {
92     DidFailOpenFileSystem(error);
93     return;
94   }
95   opened_ = true;
96   root_url_ = root;
97   reply_context_.params.set_result(PP_OK);
98   host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply());
99   reply_context_ = ppapi::host::ReplyMessageContext();
100 }
101 
DidFailOpenFileSystem(base::File::Error error)102 void PepperFileSystemHost::DidFailOpenFileSystem(base::File::Error error) {
103   int32_t pp_error = ppapi::FileErrorToPepperError(error);
104   opened_ = (pp_error == PP_OK);
105   reply_context_.params.set_result(pp_error);
106   host()->SendReply(reply_context_, PpapiPluginMsg_FileSystem_OpenReply());
107   reply_context_ = ppapi::host::ReplyMessageContext();
108 }
109 
OnHostMsgOpen(ppapi::host::HostMessageContext * context,int64_t expected_size)110 int32_t PepperFileSystemHost::OnHostMsgOpen(
111     ppapi::host::HostMessageContext* context,
112     int64_t expected_size) {
113   // Not allow multiple opens.
114   if (called_open_)
115     return PP_ERROR_INPROGRESS;
116   called_open_ = true;
117 
118   base::Optional<blink::mojom::FileSystemType> file_system_type =
119       PepperFileSystemTypeToMojoFileSystemType(type_);
120   if (!file_system_type.has_value())
121     return PP_ERROR_FAILED;
122 
123   GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
124   if (!document_url.is_valid())
125     return PP_ERROR_FAILED;
126 
127   reply_context_ = context->MakeReplyMessageContext();
128   GetFileSystemManager().Open(
129       url::Origin::Create(document_url), file_system_type.value(),
130       base::BindOnce(&PepperFileSystemHost::DidOpenFileSystem, AsWeakPtr()));
131   return PP_OK_COMPLETIONPENDING;
132 }
133 
OnHostMsgInitIsolatedFileSystem(ppapi::host::HostMessageContext * context,const std::string & fsid,PP_IsolatedFileSystemType_Private type)134 int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
135     ppapi::host::HostMessageContext* context,
136     const std::string& fsid,
137     PP_IsolatedFileSystemType_Private type) {
138   // Do not allow multiple opens.
139   if (called_open_)
140     return PP_ERROR_INPROGRESS;
141   called_open_ = true;
142 
143   // Do a sanity check.
144   if (!storage::ValidateIsolatedFileSystemId(fsid))
145     return PP_ERROR_BADARGUMENT;
146 
147   RenderView* view =
148       renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
149   if (!view)
150     return PP_ERROR_FAILED;
151 
152   url::Origin main_frame_origin(
153       view->GetWebView()->MainFrame()->GetSecurityOrigin());
154   const std::string root_name = ppapi::IsolatedFileSystemTypeToRootName(type);
155   if (root_name.empty())
156     return PP_ERROR_BADARGUMENT;
157   root_url_ = GURL(storage::GetIsolatedFileSystemRootURIString(
158       main_frame_origin.GetURL(), fsid, root_name));
159   opened_ = true;
160   return PP_OK;
161 }
162 
GetFileSystemManager()163 blink::mojom::FileSystemManager& PepperFileSystemHost::GetFileSystemManager() {
164   if (!file_system_manager_) {
165     ChildThreadImpl::current()->BindHostReceiver(
166         file_system_manager_.BindNewPipeAndPassReceiver());
167   }
168   return *file_system_manager_;
169 }
170 
171 }  // namespace content
172