1 // Copyright (c) 2012 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.
5 #include "content/child/fileapi/file_system_dispatcher.h"
7 #include "base/callback.h"
8 #include "base/file_util.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/process/process.h"
11 #include "content/child/child_thread.h"
12 #include "content/common/fileapi/file_system_messages.h"
13 #include "webkit/common/fileapi/file_system_info.h"
17 class FileSystemDispatcher::CallbackDispatcher {
19 typedef CallbackDispatcher self;
20 typedef FileSystemDispatcher::StatusCallback StatusCallback;
21 typedef FileSystemDispatcher::MetadataCallback MetadataCallback;
22 typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback;
23 typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback;
24 typedef FileSystemDispatcher::ResolveURLCallback ResolveURLCallback;
25 typedef FileSystemDispatcher::WriteCallback WriteCallback;
26 typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback;
28 static CallbackDispatcher* Create(const StatusCallback& callback) {
29 CallbackDispatcher* dispatcher = new CallbackDispatcher;
30 dispatcher->status_callback_ = callback;
31 dispatcher->error_callback_ = callback;
34 static CallbackDispatcher* Create(const MetadataCallback& callback,
35 const StatusCallback& error_callback) {
36 CallbackDispatcher* dispatcher = new CallbackDispatcher;
37 dispatcher->metadata_callback_ = callback;
38 dispatcher->error_callback_ = error_callback;
41 static CallbackDispatcher* Create(const CreateSnapshotFileCallback& callback,
42 const StatusCallback& error_callback) {
43 CallbackDispatcher* dispatcher = new CallbackDispatcher;
44 dispatcher->snapshot_callback_ = callback;
45 dispatcher->error_callback_ = error_callback;
48 static CallbackDispatcher* Create(const ReadDirectoryCallback& callback,
49 const StatusCallback& error_callback) {
50 CallbackDispatcher* dispatcher = new CallbackDispatcher;
51 dispatcher->directory_callback_ = callback;
52 dispatcher->error_callback_ = error_callback;
55 static CallbackDispatcher* Create(const OpenFileSystemCallback& callback,
56 const StatusCallback& error_callback) {
57 CallbackDispatcher* dispatcher = new CallbackDispatcher;
58 dispatcher->filesystem_callback_ = callback;
59 dispatcher->error_callback_ = error_callback;
62 static CallbackDispatcher* Create(const ResolveURLCallback& callback,
63 const StatusCallback& error_callback) {
64 CallbackDispatcher* dispatcher = new CallbackDispatcher;
65 dispatcher->resolve_callback_ = callback;
66 dispatcher->error_callback_ = error_callback;
69 static CallbackDispatcher* Create(const WriteCallback& callback,
70 const StatusCallback& error_callback) {
71 CallbackDispatcher* dispatcher = new CallbackDispatcher;
72 dispatcher->write_callback_ = callback;
73 dispatcher->error_callback_ = error_callback;
76 static CallbackDispatcher* Create(const OpenFileCallback& callback,
77 const StatusCallback& error_callback) {
78 CallbackDispatcher* dispatcher = new CallbackDispatcher;
79 dispatcher->open_callback_ = callback;
80 dispatcher->error_callback_ = error_callback;
84 ~CallbackDispatcher() {}
87 status_callback_.Run(base::PLATFORM_FILE_OK);
90 void DidFail(base::PlatformFileError error_code) {
91 error_callback_.Run(error_code);
95 const base::PlatformFileInfo& file_info) {
96 metadata_callback_.Run(file_info);
99 void DidCreateSnapshotFile(
100 const base::PlatformFileInfo& file_info,
101 const base::FilePath& platform_path,
103 snapshot_callback_.Run(file_info, platform_path, request_id);
106 void DidReadDirectory(
107 const std::vector<fileapi::DirectoryEntry>& entries,
109 directory_callback_.Run(entries, has_more);
112 void DidOpenFileSystem(const std::string& name,
114 filesystem_callback_.Run(name, root);
117 void DidResolveURL(const fileapi::FileSystemInfo& info,
118 const base::FilePath& file_path,
120 resolve_callback_.Run(info, file_path, is_directory);
123 void DidWrite(int64 bytes, bool complete) {
124 write_callback_.Run(bytes, complete);
127 void DidOpenFile(base::PlatformFile file,
129 quota::QuotaLimitType quota_policy) {
130 open_callback_.Run(file, file_open_id, quota_policy);
134 CallbackDispatcher() {}
136 StatusCallback status_callback_;
137 MetadataCallback metadata_callback_;
138 CreateSnapshotFileCallback snapshot_callback_;
139 ReadDirectoryCallback directory_callback_;
140 OpenFileSystemCallback filesystem_callback_;
141 ResolveURLCallback resolve_callback_;
142 WriteCallback write_callback_;
143 OpenFileCallback open_callback_;
145 StatusCallback error_callback_;
147 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher);
150 FileSystemDispatcher::FileSystemDispatcher() {
153 FileSystemDispatcher::~FileSystemDispatcher() {
154 // Make sure we fire all the remaining callbacks.
155 for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator
156 iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) {
157 int request_id = iter.GetCurrentKey();
158 CallbackDispatcher* dispatcher = iter.GetCurrentValue();
160 dispatcher->DidFail(base::PLATFORM_FILE_ERROR_ABORT);
161 dispatchers_.Remove(request_id);
165 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
167 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg)
168 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem)
169 IPC_MESSAGE_HANDLER(FileSystemMsg_DidResolveURL, OnDidResolveURL)
170 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed)
171 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory)
172 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata)
173 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile,
174 OnDidCreateSnapshotFile)
175 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
176 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
177 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile, OnDidOpenFile)
178 IPC_MESSAGE_UNHANDLED(handled = false)
179 IPC_END_MESSAGE_MAP()
183 void FileSystemDispatcher::OpenFileSystem(
184 const GURL& origin_url,
185 fileapi::FileSystemType type,
186 const OpenFileSystemCallback& success_callback,
187 const StatusCallback& error_callback) {
188 int request_id = dispatchers_.Add(
189 CallbackDispatcher::Create(success_callback, error_callback));
190 ChildThread::current()->Send(new FileSystemHostMsg_OpenFileSystem(
191 request_id, origin_url, type));
194 void FileSystemDispatcher::ResolveURL(
195 const GURL& filesystem_url,
196 const ResolveURLCallback& success_callback,
197 const StatusCallback& error_callback) {
198 int request_id = dispatchers_.Add(
199 CallbackDispatcher::Create(success_callback, error_callback));
200 ChildThread::current()->Send(new FileSystemHostMsg_ResolveURL(
201 request_id, filesystem_url));
204 void FileSystemDispatcher::DeleteFileSystem(
205 const GURL& origin_url,
206 fileapi::FileSystemType type,
207 const StatusCallback& callback) {
208 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
209 ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
210 request_id, origin_url, type));
213 void FileSystemDispatcher::Move(
214 const GURL& src_path,
215 const GURL& dest_path,
216 const StatusCallback& callback) {
217 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
218 ChildThread::current()->Send(new FileSystemHostMsg_Move(
219 request_id, src_path, dest_path));
222 void FileSystemDispatcher::Copy(
223 const GURL& src_path,
224 const GURL& dest_path,
225 const StatusCallback& callback) {
226 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
227 ChildThread::current()->Send(new FileSystemHostMsg_Copy(
228 request_id, src_path, dest_path));
231 void FileSystemDispatcher::Remove(
234 const StatusCallback& callback) {
235 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
236 ChildThread::current()->Send(
237 new FileSystemHostMsg_Remove(request_id, path, recursive));
240 void FileSystemDispatcher::ReadMetadata(
242 const MetadataCallback& success_callback,
243 const StatusCallback& error_callback) {
244 int request_id = dispatchers_.Add(
245 CallbackDispatcher::Create(success_callback, error_callback));
246 ChildThread::current()->Send(
247 new FileSystemHostMsg_ReadMetadata(request_id, path));
250 void FileSystemDispatcher::CreateFile(
253 const StatusCallback& callback) {
254 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
255 ChildThread::current()->Send(new FileSystemHostMsg_Create(
256 request_id, path, exclusive,
257 false /* is_directory */, false /* recursive */));
260 void FileSystemDispatcher::CreateDirectory(
264 const StatusCallback& callback) {
265 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
266 ChildThread::current()->Send(new FileSystemHostMsg_Create(
267 request_id, path, exclusive, true /* is_directory */, recursive));
270 void FileSystemDispatcher::Exists(
273 const StatusCallback& callback) {
274 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
275 ChildThread::current()->Send(
276 new FileSystemHostMsg_Exists(request_id, path, is_directory));
279 void FileSystemDispatcher::ReadDirectory(
281 const ReadDirectoryCallback& success_callback,
282 const StatusCallback& error_callback) {
283 int request_id = dispatchers_.Add(
284 CallbackDispatcher::Create(success_callback, error_callback));
285 ChildThread::current()->Send(
286 new FileSystemHostMsg_ReadDirectory(request_id, path));
289 void FileSystemDispatcher::Truncate(
293 const StatusCallback& callback) {
294 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
295 ChildThread::current()->Send(
296 new FileSystemHostMsg_Truncate(request_id, path, offset));
299 *request_id_out = request_id;
302 void FileSystemDispatcher::WriteDeprecated(
304 const GURL& blob_url,
307 const WriteCallback& success_callback,
308 const StatusCallback& error_callback) {
309 int request_id = dispatchers_.Add(
310 CallbackDispatcher::Create(success_callback, error_callback));
311 ChildThread::current()->Send(
312 new FileSystemHostMsg_WriteDeprecated(request_id, path,
316 *request_id_out = request_id;
319 void FileSystemDispatcher::Write(
321 const std::string& blob_id,
324 const WriteCallback& success_callback,
325 const StatusCallback& error_callback) {
326 int request_id = dispatchers_.Add(
327 CallbackDispatcher::Create(success_callback, error_callback));
328 ChildThread::current()->Send(
329 new FileSystemHostMsg_Write(request_id, path, blob_id, offset));
332 *request_id_out = request_id;
335 void FileSystemDispatcher::Cancel(
336 int request_id_to_cancel,
337 const StatusCallback& callback) {
338 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
339 ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite(
340 request_id, request_id_to_cancel));
343 void FileSystemDispatcher::TouchFile(
345 const base::Time& last_access_time,
346 const base::Time& last_modified_time,
347 const StatusCallback& callback) {
348 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
349 ChildThread::current()->Send(
350 new FileSystemHostMsg_TouchFile(
351 request_id, path, last_access_time, last_modified_time));
354 void FileSystemDispatcher::OpenPepperFile(
355 const GURL& file_path,
357 const OpenFileCallback& success_callback,
358 const StatusCallback& error_callback) {
359 int request_id = dispatchers_.Add(
360 CallbackDispatcher::Create(success_callback, error_callback));
361 ChildThread::current()->Send(
362 new FileSystemHostMsg_OpenPepperFile(
363 request_id, file_path, pp_open_flags));
366 void FileSystemDispatcher::NotifyCloseFile(int file_open_id) {
367 ChildThread::current()->Send(
368 new FileSystemHostMsg_NotifyCloseFile(file_open_id));
371 void FileSystemDispatcher::CreateSnapshotFile(
372 const GURL& file_path,
373 const CreateSnapshotFileCallback& success_callback,
374 const StatusCallback& error_callback) {
375 int request_id = dispatchers_.Add(
376 CallbackDispatcher::Create(success_callback, error_callback));
377 ChildThread::current()->Send(
378 new FileSystemHostMsg_CreateSnapshotFile(
379 request_id, file_path));
382 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
383 const std::string& name,
385 DCHECK(root.is_valid());
386 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
388 dispatcher->DidOpenFileSystem(name, root);
389 dispatchers_.Remove(request_id);
392 void FileSystemDispatcher::OnDidResolveURL(int request_id,
393 const fileapi::FileSystemInfo& info,
394 const base::FilePath& file_path,
396 DCHECK(info.root_url.is_valid());
397 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
399 dispatcher->DidResolveURL(info, file_path, is_directory);
400 dispatchers_.Remove(request_id);
403 void FileSystemDispatcher::OnDidSucceed(int request_id) {
404 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
406 dispatcher->DidSucceed();
407 dispatchers_.Remove(request_id);
410 void FileSystemDispatcher::OnDidReadMetadata(
411 int request_id, const base::PlatformFileInfo& file_info) {
412 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
414 dispatcher->DidReadMetadata(file_info);
415 dispatchers_.Remove(request_id);
418 void FileSystemDispatcher::OnDidCreateSnapshotFile(
419 int request_id, const base::PlatformFileInfo& file_info,
420 const base::FilePath& platform_path) {
421 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
423 dispatcher->DidCreateSnapshotFile(file_info, platform_path, request_id);
424 dispatchers_.Remove(request_id);
427 void FileSystemDispatcher::OnDidReadDirectory(
429 const std::vector<fileapi::DirectoryEntry>& entries,
431 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
433 dispatcher->DidReadDirectory(entries, has_more);
434 dispatchers_.Remove(request_id);
437 void FileSystemDispatcher::OnDidFail(
438 int request_id, base::PlatformFileError error_code) {
439 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
441 dispatcher->DidFail(error_code);
442 dispatchers_.Remove(request_id);
445 void FileSystemDispatcher::OnDidWrite(
446 int request_id, int64 bytes, bool complete) {
447 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
449 dispatcher->DidWrite(bytes, complete);
451 dispatchers_.Remove(request_id);
454 void FileSystemDispatcher::OnDidOpenFile(
456 IPC::PlatformFileForTransit file,
458 quota::QuotaLimitType quota_policy) {
459 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
461 dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
464 dispatchers_.Remove(request_id);
467 } // namespace content