- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / pepper / pepper_file_system_browser_host.cc
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_system_browser_host.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "content/public/browser/browser_ppapi_host.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/storage_partition.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/host/dispatch_host_message.h"
15 #include "ppapi/host/ppapi_host.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/shared_impl/file_type_conversion.h"
18 #include "webkit/browser/fileapi/file_system_context.h"
19 #include "webkit/browser/fileapi/file_system_operation_runner.h"
20 #include "webkit/common/fileapi/file_system_util.h"
21
22 namespace content {
23
24 namespace {
25
26 scoped_refptr<fileapi::FileSystemContext>
27 GetFileSystemContextFromRenderId(int render_process_id) {
28   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
29   RenderProcessHost* render_process_host =
30       RenderProcessHost::FromID(render_process_id);
31   if (!render_process_host)
32     return NULL;
33   StoragePartition* storage_partition =
34       render_process_host->GetStoragePartition();
35   if (!storage_partition)
36     return NULL;
37   return storage_partition->GetFileSystemContext();
38 }
39
40 }  // namespace
41
42 PepperFileSystemBrowserHost::PepperFileSystemBrowserHost(BrowserPpapiHost* host,
43                                                          PP_Instance instance,
44                                                          PP_Resource resource,
45                                                          PP_FileSystemType type)
46     : ResourceHost(host->GetPpapiHost(), instance, resource),
47       browser_ppapi_host_(host),
48       type_(type),
49       opened_(false),
50       fs_context_(NULL),
51       called_open_(false),
52       weak_factory_(this) {
53 }
54
55 void PepperFileSystemBrowserHost::OpenExisting(const GURL& root_url,
56                                                const base::Closure& callback) {
57   root_url_ = root_url;
58   int render_process_id = 0;
59   int unused;
60   if (!browser_ppapi_host_->GetRenderViewIDsForInstance(
61            pp_instance(), &render_process_id, &unused)) {
62     NOTREACHED();
63   }
64   called_open_ = true;
65   // Get the file system context asynchronously, and then complete the Open
66   // operation by calling |callback|.
67   BrowserThread::PostTaskAndReplyWithResult(
68       BrowserThread::UI,
69       FROM_HERE,
70       base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
71       base::Bind(&PepperFileSystemBrowserHost::OpenExistingWithContext,
72                  weak_factory_.GetWeakPtr(), callback));
73 }
74
75 PepperFileSystemBrowserHost::~PepperFileSystemBrowserHost() {
76   // TODO(teravest): Create a FileSystemOperationRunner
77   // per-PepperFileSystemBrowserHost, force users of this FileSystem to use it,
78   // and call Shutdown() on it here.
79 }
80
81 int32_t PepperFileSystemBrowserHost::OnResourceMessageReceived(
82     const IPC::Message& msg,
83     ppapi::host::HostMessageContext* context) {
84   IPC_BEGIN_MESSAGE_MAP(PepperFileSystemBrowserHost, msg)
85     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
86         PpapiHostMsg_FileSystem_Open,
87         OnHostMsgOpen)
88     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
89         PpapiHostMsg_FileSystem_InitIsolatedFileSystem,
90         OnHostMsgInitIsolatedFileSystem)
91   IPC_END_MESSAGE_MAP()
92   return PP_ERROR_FAILED;
93 }
94
95 bool PepperFileSystemBrowserHost::IsFileSystemHost() {
96   return true;
97 }
98
99 int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
100     ppapi::host::HostMessageContext* context,
101     int64_t /* unused */) {
102   // TODO(raymes): The file system size is now unused by FileSystemDispatcher.
103   // Figure out why. Why is the file system size signed?
104
105   // Not allow multiple opens.
106   if (called_open_)
107     return PP_ERROR_INPROGRESS;
108   called_open_ = true;
109
110   fileapi::FileSystemType file_system_type;
111   switch (type_) {
112     case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
113       file_system_type = fileapi::kFileSystemTypeTemporary;
114       break;
115     case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
116       file_system_type = fileapi::kFileSystemTypePersistent;
117       break;
118     case PP_FILESYSTEMTYPE_EXTERNAL:
119       file_system_type = fileapi::kFileSystemTypeExternal;
120       break;
121     default:
122       return PP_ERROR_FAILED;
123   }
124
125   int render_process_id = 0;
126   int unused;
127   if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
128                                                         &render_process_id,
129                                                         &unused)) {
130       return PP_ERROR_FAILED;
131   }
132   BrowserThread::PostTaskAndReplyWithResult(
133       BrowserThread::UI,
134       FROM_HERE,
135       base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
136       base::Bind(&PepperFileSystemBrowserHost::GotFileSystemContext,
137                  weak_factory_.GetWeakPtr(),
138                  context->MakeReplyMessageContext(),
139                  file_system_type));
140   return PP_OK_COMPLETIONPENDING;
141 }
142
143 void PepperFileSystemBrowserHost::OpenExistingWithContext(
144     const base::Closure& callback,
145     scoped_refptr<fileapi::FileSystemContext> fs_context) {
146   if (fs_context.get()) {
147     opened_ = true;
148   } else {
149     // If there is no file system context, we log a warning and continue with an
150     // invalid resource (which will produce errors when used), since we have no
151     // way to communicate the error to the caller.
152     LOG(WARNING) << "Could not retrieve file system context.";
153   }
154   fs_context_ = fs_context;
155   callback.Run();
156 }
157
158 void PepperFileSystemBrowserHost::GotFileSystemContext(
159     ppapi::host::ReplyMessageContext reply_context,
160     fileapi::FileSystemType file_system_type,
161     scoped_refptr<fileapi::FileSystemContext> fs_context) {
162   if (!fs_context.get()) {
163     OpenFileSystemComplete(
164         reply_context, GURL(), std::string(), base::PLATFORM_FILE_ERROR_FAILED);
165     return;
166   }
167   GURL origin = browser_ppapi_host_->GetDocumentURLForInstance(
168       pp_instance()).GetOrigin();
169   fs_context->OpenFileSystem(origin, file_system_type,
170       fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
171       base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete,
172                  weak_factory_.GetWeakPtr(),
173                  reply_context));
174   fs_context_ = fs_context;
175 }
176
177 void PepperFileSystemBrowserHost::GotIsolatedFileSystemContext(
178     ppapi::host::ReplyMessageContext reply_context,
179     scoped_refptr<fileapi::FileSystemContext> fs_context) {
180   fs_context_ = fs_context;
181   if (fs_context.get())
182     reply_context.params.set_result(PP_OK);
183   else
184     reply_context.params.set_result(PP_ERROR_FAILED);
185   host()->SendReply(reply_context,
186                     PpapiPluginMsg_FileSystem_InitIsolatedFileSystemReply());
187 }
188
189 void PepperFileSystemBrowserHost::OpenFileSystemComplete(
190     ppapi::host::ReplyMessageContext reply_context,
191     const GURL& root,
192     const std::string& /* unused */,
193     base::PlatformFileError error) {
194   int32 pp_error = ppapi::PlatformFileErrorToPepperError(error);
195   if (pp_error == PP_OK) {
196     opened_ = true;
197     root_url_ = root;
198   }
199   reply_context.params.set_result(pp_error);
200   host()->SendReply(reply_context, PpapiPluginMsg_FileSystem_OpenReply());
201 }
202
203 int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
204     ppapi::host::HostMessageContext* context,
205     const std::string& fsid) {
206   // Do not allow multiple opens.
207   if (called_open_)
208     return PP_ERROR_INPROGRESS;
209   called_open_ = true;
210   // Do a sanity check.
211   if (!fileapi::ValidateIsolatedFileSystemId(fsid))
212     return PP_ERROR_BADARGUMENT;
213   const GURL& url =
214       browser_ppapi_host_->GetDocumentURLForInstance(pp_instance());
215   root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
216       url.GetOrigin(), fsid, "crxfs"));
217   opened_ = true;
218
219   int render_process_id = 0;
220   int unused;
221   if (!browser_ppapi_host_->GetRenderViewIDsForInstance(pp_instance(),
222                                                         &render_process_id,
223                                                         &unused)) {
224     return PP_ERROR_FAILED;
225   }
226   BrowserThread::PostTaskAndReplyWithResult(
227       BrowserThread::UI,
228       FROM_HERE,
229       base::Bind(&GetFileSystemContextFromRenderId, render_process_id),
230       base::Bind(&PepperFileSystemBrowserHost::GotIsolatedFileSystemContext,
231                  weak_factory_.GetWeakPtr(),
232                  context->MakeReplyMessageContext()));
233   return PP_OK_COMPLETIONPENDING;
234 }
235
236 }  // namespace content