| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "content/common/fileapi/file_system_dispatcher.h" | |
| 6 | |
| 7 #include "base/callback.h" | |
| 8 #include "base/file_util.h" | |
| 9 #include "base/process.h" | |
| 10 #include "content/common/child_thread.h" | |
| 11 #include "content/common/fileapi/file_system_messages.h" | |
| 12 | |
| 13 namespace content { | |
| 14 | |
| 15 class FileSystemDispatcher::CallbackDispatcher { | |
| 16 public: | |
| 17 typedef CallbackDispatcher self; | |
| 18 typedef FileSystemDispatcher::StatusCallback StatusCallback; | |
| 19 typedef FileSystemDispatcher::MetadataCallback MetadataCallback; | |
| 20 typedef FileSystemDispatcher::ReadDirectoryCallback ReadDirectoryCallback; | |
| 21 typedef FileSystemDispatcher::OpenFileSystemCallback OpenFileSystemCallback; | |
| 22 typedef FileSystemDispatcher::WriteCallback WriteCallback; | |
| 23 typedef FileSystemDispatcher::OpenFileCallback OpenFileCallback; | |
| 24 | |
| 25 static CallbackDispatcher* Create(const StatusCallback& callback) { | |
| 26 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 27 dispatcher->status_callback_ = callback; | |
| 28 dispatcher->error_callback_ = callback; | |
| 29 return dispatcher; | |
| 30 } | |
| 31 static CallbackDispatcher* Create(const MetadataCallback& callback, | |
| 32 const StatusCallback& error_callback) { | |
| 33 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 34 dispatcher->metadata_callback_ = callback; | |
| 35 dispatcher->error_callback_ = error_callback; | |
| 36 return dispatcher; | |
| 37 } | |
| 38 static CallbackDispatcher* Create(const ReadDirectoryCallback& callback, | |
| 39 const StatusCallback& error_callback) { | |
| 40 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 41 dispatcher->directory_callback_ = callback; | |
| 42 dispatcher->error_callback_ = error_callback; | |
| 43 return dispatcher; | |
| 44 } | |
| 45 static CallbackDispatcher* Create(const OpenFileSystemCallback& callback, | |
| 46 const StatusCallback& error_callback) { | |
| 47 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 48 dispatcher->filesystem_callback_ = callback; | |
| 49 dispatcher->error_callback_ = error_callback; | |
| 50 return dispatcher; | |
| 51 } | |
| 52 static CallbackDispatcher* Create(const WriteCallback& callback, | |
| 53 const StatusCallback& error_callback) { | |
| 54 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 55 dispatcher->write_callback_ = callback; | |
| 56 dispatcher->error_callback_ = error_callback; | |
| 57 return dispatcher; | |
| 58 } | |
| 59 static CallbackDispatcher* Create(const OpenFileCallback& callback, | |
| 60 const StatusCallback& error_callback) { | |
| 61 CallbackDispatcher* dispatcher = new CallbackDispatcher; | |
| 62 dispatcher->open_callback_ = callback; | |
| 63 dispatcher->error_callback_ = error_callback; | |
| 64 return dispatcher; | |
| 65 } | |
| 66 | |
| 67 ~CallbackDispatcher() {} | |
| 68 | |
| 69 void DidSucceed() { | |
| 70 status_callback_.Run(base::PLATFORM_FILE_OK); | |
| 71 } | |
| 72 | |
| 73 void DidFail(base::PlatformFileError error_code) { | |
| 74 error_callback_.Run(error_code); | |
| 75 } | |
| 76 | |
| 77 void DidReadMetadata( | |
| 78 const base::PlatformFileInfo& file_info, | |
| 79 const base::FilePath& platform_path) { | |
| 80 metadata_callback_.Run(file_info, platform_path); | |
| 81 } | |
| 82 | |
| 83 void DidCreateSnapshotFile( | |
| 84 const base::PlatformFileInfo& file_info, | |
| 85 const base::FilePath& platform_path) { | |
| 86 metadata_callback_.Run(file_info, platform_path); | |
| 87 } | |
| 88 | |
| 89 void DidReadDirectory( | |
| 90 const std::vector<fileapi::DirectoryEntry>& entries, | |
| 91 bool has_more) { | |
| 92 directory_callback_.Run(entries, has_more); | |
| 93 } | |
| 94 | |
| 95 void DidOpenFileSystem(const std::string& name, | |
| 96 const GURL& root) { | |
| 97 filesystem_callback_.Run(name, root); | |
| 98 } | |
| 99 | |
| 100 void DidWrite(int64 bytes, bool complete) { | |
| 101 write_callback_.Run(bytes, complete); | |
| 102 } | |
| 103 | |
| 104 void DidOpenFile(base::PlatformFile file, | |
| 105 int file_open_id, | |
| 106 quota::QuotaLimitType quota_policy) { | |
| 107 open_callback_.Run(file, file_open_id, quota_policy); | |
| 108 } | |
| 109 | |
| 110 private: | |
| 111 CallbackDispatcher() {} | |
| 112 | |
| 113 StatusCallback status_callback_; | |
| 114 MetadataCallback metadata_callback_; | |
| 115 ReadDirectoryCallback directory_callback_; | |
| 116 OpenFileSystemCallback filesystem_callback_; | |
| 117 WriteCallback write_callback_; | |
| 118 OpenFileCallback open_callback_; | |
| 119 | |
| 120 StatusCallback error_callback_; | |
| 121 | |
| 122 DISALLOW_COPY_AND_ASSIGN(CallbackDispatcher); | |
| 123 }; | |
| 124 | |
| 125 FileSystemDispatcher::FileSystemDispatcher() { | |
| 126 } | |
| 127 | |
| 128 FileSystemDispatcher::~FileSystemDispatcher() { | |
| 129 // Make sure we fire all the remaining callbacks. | |
| 130 for (IDMap<CallbackDispatcher, IDMapOwnPointer>::iterator | |
| 131 iter(&dispatchers_); !iter.IsAtEnd(); iter.Advance()) { | |
| 132 int request_id = iter.GetCurrentKey(); | |
| 133 CallbackDispatcher* dispatcher = iter.GetCurrentValue(); | |
| 134 DCHECK(dispatcher); | |
| 135 dispatcher->DidFail(base::PLATFORM_FILE_ERROR_ABORT); | |
| 136 dispatchers_.Remove(request_id); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) { | |
| 141 bool handled = true; | |
| 142 IPC_BEGIN_MESSAGE_MAP(FileSystemDispatcher, msg) | |
| 143 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFileSystem, OnDidOpenFileSystem) | |
| 144 IPC_MESSAGE_HANDLER(FileSystemMsg_DidSucceed, OnDidSucceed) | |
| 145 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadDirectory, OnDidReadDirectory) | |
| 146 IPC_MESSAGE_HANDLER(FileSystemMsg_DidReadMetadata, OnDidReadMetadata) | |
| 147 IPC_MESSAGE_HANDLER(FileSystemMsg_DidCreateSnapshotFile, | |
| 148 OnDidCreateSnapshotFile) | |
| 149 IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail) | |
| 150 IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite) | |
| 151 IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile, OnDidOpenFile) | |
| 152 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 153 IPC_END_MESSAGE_MAP() | |
| 154 return handled; | |
| 155 } | |
| 156 | |
| 157 bool FileSystemDispatcher::OpenFileSystem( | |
| 158 const GURL& origin_url, fileapi::FileSystemType type, | |
| 159 long long size, bool create, | |
| 160 const OpenFileSystemCallback& success_callback, | |
| 161 const StatusCallback& error_callback) { | |
| 162 int request_id = dispatchers_.Add( | |
| 163 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 164 if (!ChildThread::current()->Send(new FileSystemHostMsg_Open( | |
| 165 request_id, origin_url, type, size, create))) { | |
| 166 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 167 return false; | |
| 168 } | |
| 169 | |
| 170 return true; | |
| 171 } | |
| 172 | |
| 173 bool FileSystemDispatcher::DeleteFileSystem( | |
| 174 const GURL& origin_url, | |
| 175 fileapi::FileSystemType type, | |
| 176 const StatusCallback& callback) { | |
| 177 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 178 if (!ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem( | |
| 179 request_id, origin_url, type))) { | |
| 180 dispatchers_.Remove(request_id); | |
| 181 return false; | |
| 182 } | |
| 183 return true; | |
| 184 } | |
| 185 | |
| 186 bool FileSystemDispatcher::Move( | |
| 187 const GURL& src_path, | |
| 188 const GURL& dest_path, | |
| 189 const StatusCallback& callback) { | |
| 190 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 191 if (!ChildThread::current()->Send(new FileSystemHostMsg_Move( | |
| 192 request_id, src_path, dest_path))) { | |
| 193 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 194 return false; | |
| 195 } | |
| 196 | |
| 197 return true; | |
| 198 } | |
| 199 | |
| 200 bool FileSystemDispatcher::Copy( | |
| 201 const GURL& src_path, | |
| 202 const GURL& dest_path, | |
| 203 const StatusCallback& callback) { | |
| 204 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 205 if (!ChildThread::current()->Send(new FileSystemHostMsg_Copy( | |
| 206 request_id, src_path, dest_path))) { | |
| 207 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 208 return false; | |
| 209 } | |
| 210 | |
| 211 return true; | |
| 212 } | |
| 213 | |
| 214 bool FileSystemDispatcher::Remove( | |
| 215 const GURL& path, | |
| 216 bool recursive, | |
| 217 const StatusCallback& callback) { | |
| 218 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 219 if (!ChildThread::current()->Send( | |
| 220 new FileSystemMsg_Remove(request_id, path, recursive))) { | |
| 221 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 222 return false; | |
| 223 } | |
| 224 | |
| 225 return true; | |
| 226 } | |
| 227 | |
| 228 bool FileSystemDispatcher::ReadMetadata( | |
| 229 const GURL& path, | |
| 230 const MetadataCallback& success_callback, | |
| 231 const StatusCallback& error_callback) { | |
| 232 int request_id = dispatchers_.Add( | |
| 233 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 234 if (!ChildThread::current()->Send( | |
| 235 new FileSystemHostMsg_ReadMetadata(request_id, path))) { | |
| 236 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 237 return false; | |
| 238 } | |
| 239 | |
| 240 return true; | |
| 241 } | |
| 242 | |
| 243 bool FileSystemDispatcher::Create( | |
| 244 const GURL& path, | |
| 245 bool exclusive, | |
| 246 bool is_directory, | |
| 247 bool recursive, | |
| 248 const StatusCallback& callback) { | |
| 249 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 250 if (!ChildThread::current()->Send(new FileSystemHostMsg_Create( | |
| 251 request_id, path, exclusive, is_directory, recursive))) { | |
| 252 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 return true; | |
| 257 } | |
| 258 | |
| 259 bool FileSystemDispatcher::Exists( | |
| 260 const GURL& path, | |
| 261 bool is_directory, | |
| 262 const StatusCallback& callback) { | |
| 263 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 264 if (!ChildThread::current()->Send( | |
| 265 new FileSystemHostMsg_Exists(request_id, path, is_directory))) { | |
| 266 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 267 return false; | |
| 268 } | |
| 269 | |
| 270 return true; | |
| 271 } | |
| 272 | |
| 273 bool FileSystemDispatcher::ReadDirectory( | |
| 274 const GURL& path, | |
| 275 const ReadDirectoryCallback& success_callback, | |
| 276 const StatusCallback& error_callback) { | |
| 277 int request_id = dispatchers_.Add( | |
| 278 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 279 if (!ChildThread::current()->Send( | |
| 280 new FileSystemHostMsg_ReadDirectory(request_id, path))) { | |
| 281 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 282 return false; | |
| 283 } | |
| 284 | |
| 285 return true; | |
| 286 } | |
| 287 | |
| 288 bool FileSystemDispatcher::Truncate( | |
| 289 const GURL& path, | |
| 290 int64 offset, | |
| 291 int* request_id_out, | |
| 292 const StatusCallback& callback) { | |
| 293 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 294 if (!ChildThread::current()->Send( | |
| 295 new FileSystemHostMsg_Truncate(request_id, path, offset))) { | |
| 296 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 297 return false; | |
| 298 } | |
| 299 | |
| 300 if (request_id_out) | |
| 301 *request_id_out = request_id; | |
| 302 return true; | |
| 303 } | |
| 304 | |
| 305 bool FileSystemDispatcher::Write( | |
| 306 const GURL& path, | |
| 307 const GURL& blob_url, | |
| 308 int64 offset, | |
| 309 int* request_id_out, | |
| 310 const WriteCallback& success_callback, | |
| 311 const StatusCallback& error_callback) { | |
| 312 int request_id = dispatchers_.Add( | |
| 313 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 314 if (!ChildThread::current()->Send( | |
| 315 new FileSystemHostMsg_Write(request_id, path, blob_url, offset))) { | |
| 316 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 317 return false; | |
| 318 } | |
| 319 | |
| 320 if (request_id_out) | |
| 321 *request_id_out = request_id; | |
| 322 return true; | |
| 323 } | |
| 324 | |
| 325 bool FileSystemDispatcher::Cancel( | |
| 326 int request_id_to_cancel, | |
| 327 const StatusCallback& callback) { | |
| 328 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 329 if (!ChildThread::current()->Send(new FileSystemHostMsg_CancelWrite( | |
| 330 request_id, request_id_to_cancel))) { | |
| 331 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 332 return false; | |
| 333 } | |
| 334 | |
| 335 return true; | |
| 336 } | |
| 337 | |
| 338 bool FileSystemDispatcher::TouchFile( | |
| 339 const GURL& path, | |
| 340 const base::Time& last_access_time, | |
| 341 const base::Time& last_modified_time, | |
| 342 const StatusCallback& callback) { | |
| 343 int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback)); | |
| 344 if (!ChildThread::current()->Send( | |
| 345 new FileSystemHostMsg_TouchFile( | |
| 346 request_id, path, last_access_time, last_modified_time))) { | |
| 347 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 348 return false; | |
| 349 } | |
| 350 | |
| 351 return true; | |
| 352 } | |
| 353 | |
| 354 bool FileSystemDispatcher::OpenFile( | |
| 355 const GURL& file_path, | |
| 356 int file_flags, | |
| 357 const OpenFileCallback& success_callback, | |
| 358 const StatusCallback& error_callback) { | |
| 359 int request_id = dispatchers_.Add( | |
| 360 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 361 if (!ChildThread::current()->Send( | |
| 362 new FileSystemHostMsg_OpenFile( | |
| 363 request_id, file_path, file_flags))) { | |
| 364 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 365 return false; | |
| 366 } | |
| 367 | |
| 368 return true; | |
| 369 } | |
| 370 | |
| 371 bool FileSystemDispatcher::NotifyCloseFile(int file_open_id) { | |
| 372 return ChildThread::current()->Send( | |
| 373 new FileSystemHostMsg_NotifyCloseFile(file_open_id)); | |
| 374 } | |
| 375 | |
| 376 bool FileSystemDispatcher::CreateSnapshotFile( | |
| 377 const GURL& file_path, | |
| 378 const CreateSnapshotFileCallback& success_callback, | |
| 379 const StatusCallback& error_callback) { | |
| 380 int request_id = dispatchers_.Add( | |
| 381 CallbackDispatcher::Create(success_callback, error_callback)); | |
| 382 if (!ChildThread::current()->Send( | |
| 383 new FileSystemHostMsg_CreateSnapshotFile( | |
| 384 request_id, file_path))) { | |
| 385 dispatchers_.Remove(request_id); // destroys |dispatcher| | |
| 386 return false; | |
| 387 } | |
| 388 return true; | |
| 389 } | |
| 390 | |
| 391 void FileSystemDispatcher::OnDidOpenFileSystem(int request_id, | |
| 392 const std::string& name, | |
| 393 const GURL& root) { | |
| 394 DCHECK(root.is_valid()); | |
| 395 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 396 DCHECK(dispatcher); | |
| 397 dispatcher->DidOpenFileSystem(name, root); | |
| 398 dispatchers_.Remove(request_id); | |
| 399 } | |
| 400 | |
| 401 void FileSystemDispatcher::OnDidSucceed(int request_id) { | |
| 402 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 403 DCHECK(dispatcher); | |
| 404 dispatcher->DidSucceed(); | |
| 405 dispatchers_.Remove(request_id); | |
| 406 } | |
| 407 | |
| 408 void FileSystemDispatcher::OnDidReadMetadata( | |
| 409 int request_id, const base::PlatformFileInfo& file_info, | |
| 410 const base::FilePath& platform_path) { | |
| 411 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 412 DCHECK(dispatcher); | |
| 413 dispatcher->DidReadMetadata(file_info, platform_path); | |
| 414 dispatchers_.Remove(request_id); | |
| 415 } | |
| 416 | |
| 417 void FileSystemDispatcher::OnDidCreateSnapshotFile( | |
| 418 int request_id, const base::PlatformFileInfo& file_info, | |
| 419 const base::FilePath& platform_path) { | |
| 420 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 421 DCHECK(dispatcher); | |
| 422 dispatcher->DidCreateSnapshotFile(file_info, platform_path); | |
| 423 dispatchers_.Remove(request_id); | |
| 424 ChildThread::current()->Send( | |
| 425 new FileSystemHostMsg_DidReceiveSnapshotFile(request_id)); | |
| 426 } | |
| 427 | |
| 428 void FileSystemDispatcher::OnDidReadDirectory( | |
| 429 int request_id, | |
| 430 const std::vector<fileapi::DirectoryEntry>& entries, | |
| 431 bool has_more) { | |
| 432 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 433 DCHECK(dispatcher); | |
| 434 dispatcher->DidReadDirectory(entries, has_more); | |
| 435 dispatchers_.Remove(request_id); | |
| 436 } | |
| 437 | |
| 438 void FileSystemDispatcher::OnDidFail( | |
| 439 int request_id, base::PlatformFileError error_code) { | |
| 440 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 441 DCHECK(dispatcher); | |
| 442 dispatcher->DidFail(error_code); | |
| 443 dispatchers_.Remove(request_id); | |
| 444 } | |
| 445 | |
| 446 void FileSystemDispatcher::OnDidWrite( | |
| 447 int request_id, int64 bytes, bool complete) { | |
| 448 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 449 DCHECK(dispatcher); | |
| 450 dispatcher->DidWrite(bytes, complete); | |
| 451 if (complete) | |
| 452 dispatchers_.Remove(request_id); | |
| 453 } | |
| 454 | |
| 455 void FileSystemDispatcher::OnDidOpenFile( | |
| 456 int request_id, | |
| 457 IPC::PlatformFileForTransit file, | |
| 458 int file_open_id, | |
| 459 quota::QuotaLimitType quota_policy) { | |
| 460 CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id); | |
| 461 DCHECK(dispatcher); | |
| 462 dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file), | |
| 463 file_open_id, | |
| 464 quota_policy); | |
| 465 dispatchers_.Remove(request_id); | |
| 466 } | |
| 467 | |
| 468 } // namespace content | |
| OLD | NEW |