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 "storage/browser/fileapi/file_system_operation_runner.h" 6 7#include "base/bind.h" 8#include "base/message_loop/message_loop_proxy.h" 9#include "base/stl_util.h" 10#include "net/url_request/url_request_context.h" 11#include "storage/browser/blob/blob_url_request_job_factory.h" 12#include "storage/browser/fileapi/file_observers.h" 13#include "storage/browser/fileapi/file_stream_writer.h" 14#include "storage/browser/fileapi/file_system_context.h" 15#include "storage/browser/fileapi/file_system_operation.h" 16#include "storage/browser/fileapi/file_writer_delegate.h" 17#include "storage/common/blob/shareable_file_reference.h" 18 19namespace storage { 20 21typedef FileSystemOperationRunner::OperationID OperationID; 22 23class FileSystemOperationRunner::BeginOperationScoper 24 : public base::SupportsWeakPtr< 25 FileSystemOperationRunner::BeginOperationScoper> { 26 public: 27 BeginOperationScoper() {} 28 private: 29 DISALLOW_COPY_AND_ASSIGN(BeginOperationScoper); 30}; 31 32FileSystemOperationRunner::OperationHandle::OperationHandle() {} 33FileSystemOperationRunner::OperationHandle::~OperationHandle() {} 34 35FileSystemOperationRunner::~FileSystemOperationRunner() { 36} 37 38void FileSystemOperationRunner::Shutdown() { 39 operations_.Clear(); 40} 41 42OperationID FileSystemOperationRunner::CreateFile( 43 const FileSystemURL& url, 44 bool exclusive, 45 const StatusCallback& callback) { 46 base::File::Error error = base::File::FILE_OK; 47 FileSystemOperation* operation = 48 file_system_context_->CreateFileSystemOperation(url, &error); 49 50 BeginOperationScoper scope; 51 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 52 if (!operation) { 53 DidFinish(handle, callback, error); 54 return handle.id; 55 } 56 PrepareForWrite(handle.id, url); 57 operation->CreateFile( 58 url, exclusive, 59 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 60 handle, callback)); 61 return handle.id; 62} 63 64OperationID FileSystemOperationRunner::CreateDirectory( 65 const FileSystemURL& url, 66 bool exclusive, 67 bool recursive, 68 const StatusCallback& callback) { 69 base::File::Error error = base::File::FILE_OK; 70 FileSystemOperation* operation = 71 file_system_context_->CreateFileSystemOperation(url, &error); 72 BeginOperationScoper scope; 73 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 74 if (!operation) { 75 DidFinish(handle, callback, error); 76 return handle.id; 77 } 78 PrepareForWrite(handle.id, url); 79 operation->CreateDirectory( 80 url, exclusive, recursive, 81 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 82 handle, callback)); 83 return handle.id; 84} 85 86OperationID FileSystemOperationRunner::Copy( 87 const FileSystemURL& src_url, 88 const FileSystemURL& dest_url, 89 CopyOrMoveOption option, 90 const CopyProgressCallback& progress_callback, 91 const StatusCallback& callback) { 92 base::File::Error error = base::File::FILE_OK; 93 FileSystemOperation* operation = 94 file_system_context_->CreateFileSystemOperation(dest_url, &error); 95 BeginOperationScoper scope; 96 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 97 if (!operation) { 98 DidFinish(handle, callback, error); 99 return handle.id; 100 } 101 PrepareForWrite(handle.id, dest_url); 102 PrepareForRead(handle.id, src_url); 103 operation->Copy( 104 src_url, dest_url, option, 105 progress_callback.is_null() ? 106 CopyProgressCallback() : 107 base::Bind(&FileSystemOperationRunner::OnCopyProgress, AsWeakPtr(), 108 handle, progress_callback), 109 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 110 handle, callback)); 111 return handle.id; 112} 113 114OperationID FileSystemOperationRunner::Move( 115 const FileSystemURL& src_url, 116 const FileSystemURL& dest_url, 117 CopyOrMoveOption option, 118 const StatusCallback& callback) { 119 base::File::Error error = base::File::FILE_OK; 120 FileSystemOperation* operation = 121 file_system_context_->CreateFileSystemOperation(dest_url, &error); 122 BeginOperationScoper scope; 123 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 124 if (!operation) { 125 DidFinish(handle, callback, error); 126 return handle.id; 127 } 128 PrepareForWrite(handle.id, dest_url); 129 PrepareForWrite(handle.id, src_url); 130 operation->Move( 131 src_url, dest_url, option, 132 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 133 handle, callback)); 134 return handle.id; 135} 136 137OperationID FileSystemOperationRunner::DirectoryExists( 138 const FileSystemURL& url, 139 const StatusCallback& callback) { 140 base::File::Error error = base::File::FILE_OK; 141 FileSystemOperation* operation = 142 file_system_context_->CreateFileSystemOperation(url, &error); 143 BeginOperationScoper scope; 144 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 145 if (!operation) { 146 DidFinish(handle, callback, error); 147 return handle.id; 148 } 149 PrepareForRead(handle.id, url); 150 operation->DirectoryExists( 151 url, 152 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 153 handle, callback)); 154 return handle.id; 155} 156 157OperationID FileSystemOperationRunner::FileExists( 158 const FileSystemURL& url, 159 const StatusCallback& callback) { 160 base::File::Error error = base::File::FILE_OK; 161 FileSystemOperation* operation = 162 file_system_context_->CreateFileSystemOperation(url, &error); 163 BeginOperationScoper scope; 164 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 165 if (!operation) { 166 DidFinish(handle, callback, error); 167 return handle.id; 168 } 169 PrepareForRead(handle.id, url); 170 operation->FileExists( 171 url, 172 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 173 handle, callback)); 174 return handle.id; 175} 176 177OperationID FileSystemOperationRunner::GetMetadata( 178 const FileSystemURL& url, 179 const GetMetadataCallback& callback) { 180 base::File::Error error = base::File::FILE_OK; 181 FileSystemOperation* operation = 182 file_system_context_->CreateFileSystemOperation(url, &error); 183 BeginOperationScoper scope; 184 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 185 if (!operation) { 186 DidGetMetadata(handle, callback, error, base::File::Info()); 187 return handle.id; 188 } 189 PrepareForRead(handle.id, url); 190 operation->GetMetadata( 191 url, 192 base::Bind(&FileSystemOperationRunner::DidGetMetadata, AsWeakPtr(), 193 handle, callback)); 194 return handle.id; 195} 196 197OperationID FileSystemOperationRunner::ReadDirectory( 198 const FileSystemURL& url, 199 const ReadDirectoryCallback& callback) { 200 base::File::Error error = base::File::FILE_OK; 201 FileSystemOperation* operation = 202 file_system_context_->CreateFileSystemOperation(url, &error); 203 BeginOperationScoper scope; 204 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 205 if (!operation) { 206 DidReadDirectory(handle, callback, error, std::vector<DirectoryEntry>(), 207 false); 208 return handle.id; 209 } 210 PrepareForRead(handle.id, url); 211 operation->ReadDirectory( 212 url, 213 base::Bind(&FileSystemOperationRunner::DidReadDirectory, AsWeakPtr(), 214 handle, callback)); 215 return handle.id; 216} 217 218OperationID FileSystemOperationRunner::Remove( 219 const FileSystemURL& url, bool recursive, 220 const StatusCallback& callback) { 221 base::File::Error error = base::File::FILE_OK; 222 FileSystemOperation* operation = 223 file_system_context_->CreateFileSystemOperation(url, &error); 224 BeginOperationScoper scope; 225 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 226 if (!operation) { 227 DidFinish(handle, callback, error); 228 return handle.id; 229 } 230 PrepareForWrite(handle.id, url); 231 operation->Remove( 232 url, recursive, 233 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 234 handle, callback)); 235 return handle.id; 236} 237 238OperationID FileSystemOperationRunner::Write( 239 const net::URLRequestContext* url_request_context, 240 const FileSystemURL& url, 241 scoped_ptr<storage::BlobDataHandle> blob, 242 int64 offset, 243 const WriteCallback& callback) { 244 base::File::Error error = base::File::FILE_OK; 245 FileSystemOperation* operation = 246 file_system_context_->CreateFileSystemOperation(url, &error); 247 248 BeginOperationScoper scope; 249 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 250 if (!operation) { 251 DidWrite(handle, callback, error, 0, true); 252 return handle.id; 253 } 254 255 scoped_ptr<FileStreamWriter> writer( 256 file_system_context_->CreateFileStreamWriter(url, offset)); 257 if (!writer) { 258 // Write is not supported. 259 DidWrite(handle, callback, base::File::FILE_ERROR_SECURITY, 0, true); 260 return handle.id; 261 } 262 263 FileWriterDelegate::FlushPolicy flush_policy = 264 file_system_context_->ShouldFlushOnWriteCompletion(url.type()) 265 ? FileWriterDelegate::FLUSH_ON_COMPLETION 266 : FileWriterDelegate::NO_FLUSH_ON_COMPLETION; 267 scoped_ptr<FileWriterDelegate> writer_delegate( 268 new FileWriterDelegate(writer.Pass(), flush_policy)); 269 270 scoped_ptr<net::URLRequest> blob_request( 271 storage::BlobProtocolHandler::CreateBlobRequest( 272 blob.Pass(), url_request_context, writer_delegate.get())); 273 274 PrepareForWrite(handle.id, url); 275 operation->Write( 276 url, writer_delegate.Pass(), blob_request.Pass(), 277 base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), 278 handle, callback)); 279 return handle.id; 280} 281 282OperationID FileSystemOperationRunner::Truncate( 283 const FileSystemURL& url, int64 length, 284 const StatusCallback& callback) { 285 base::File::Error error = base::File::FILE_OK; 286 FileSystemOperation* operation = 287 file_system_context_->CreateFileSystemOperation(url, &error); 288 BeginOperationScoper scope; 289 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 290 if (!operation) { 291 DidFinish(handle, callback, error); 292 return handle.id; 293 } 294 PrepareForWrite(handle.id, url); 295 operation->Truncate( 296 url, length, 297 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 298 handle, callback)); 299 return handle.id; 300} 301 302void FileSystemOperationRunner::Cancel( 303 OperationID id, 304 const StatusCallback& callback) { 305 if (ContainsKey(finished_operations_, id)) { 306 DCHECK(!ContainsKey(stray_cancel_callbacks_, id)); 307 stray_cancel_callbacks_[id] = callback; 308 return; 309 } 310 FileSystemOperation* operation = operations_.Lookup(id); 311 if (!operation) { 312 // There is no operation with |id|. 313 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); 314 return; 315 } 316 operation->Cancel(callback); 317} 318 319OperationID FileSystemOperationRunner::TouchFile( 320 const FileSystemURL& url, 321 const base::Time& last_access_time, 322 const base::Time& last_modified_time, 323 const StatusCallback& callback) { 324 base::File::Error error = base::File::FILE_OK; 325 FileSystemOperation* operation = 326 file_system_context_->CreateFileSystemOperation(url, &error); 327 BeginOperationScoper scope; 328 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 329 if (!operation) { 330 DidFinish(handle, callback, error); 331 return handle.id; 332 } 333 PrepareForWrite(handle.id, url); 334 operation->TouchFile( 335 url, last_access_time, last_modified_time, 336 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 337 handle, callback)); 338 return handle.id; 339} 340 341OperationID FileSystemOperationRunner::OpenFile( 342 const FileSystemURL& url, 343 int file_flags, 344 const OpenFileCallback& callback) { 345 base::File::Error error = base::File::FILE_OK; 346 FileSystemOperation* operation = 347 file_system_context_->CreateFileSystemOperation(url, &error); 348 BeginOperationScoper scope; 349 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 350 if (!operation) { 351 DidOpenFile(handle, callback, base::File(error), base::Closure()); 352 return handle.id; 353 } 354 if (file_flags & 355 (base::File::FLAG_CREATE | base::File::FLAG_OPEN_ALWAYS | 356 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_TRUNCATED | 357 base::File::FLAG_WRITE | base::File::FLAG_EXCLUSIVE_WRITE | 358 base::File::FLAG_DELETE_ON_CLOSE | 359 base::File::FLAG_WRITE_ATTRIBUTES)) { 360 PrepareForWrite(handle.id, url); 361 } else { 362 PrepareForRead(handle.id, url); 363 } 364 operation->OpenFile( 365 url, file_flags, 366 base::Bind(&FileSystemOperationRunner::DidOpenFile, AsWeakPtr(), 367 handle, callback)); 368 return handle.id; 369} 370 371OperationID FileSystemOperationRunner::CreateSnapshotFile( 372 const FileSystemURL& url, 373 const SnapshotFileCallback& callback) { 374 base::File::Error error = base::File::FILE_OK; 375 FileSystemOperation* operation = 376 file_system_context_->CreateFileSystemOperation(url, &error); 377 BeginOperationScoper scope; 378 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 379 if (!operation) { 380 DidCreateSnapshot(handle, callback, error, base::File::Info(), 381 base::FilePath(), NULL); 382 return handle.id; 383 } 384 PrepareForRead(handle.id, url); 385 operation->CreateSnapshotFile( 386 url, 387 base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, AsWeakPtr(), 388 handle, callback)); 389 return handle.id; 390} 391 392OperationID FileSystemOperationRunner::CopyInForeignFile( 393 const base::FilePath& src_local_disk_path, 394 const FileSystemURL& dest_url, 395 const StatusCallback& callback) { 396 base::File::Error error = base::File::FILE_OK; 397 FileSystemOperation* operation = 398 file_system_context_->CreateFileSystemOperation(dest_url, &error); 399 BeginOperationScoper scope; 400 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 401 if (!operation) { 402 DidFinish(handle, callback, error); 403 return handle.id; 404 } 405 PrepareForWrite(handle.id, dest_url); 406 operation->CopyInForeignFile( 407 src_local_disk_path, dest_url, 408 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 409 handle, callback)); 410 return handle.id; 411} 412 413OperationID FileSystemOperationRunner::RemoveFile( 414 const FileSystemURL& url, 415 const StatusCallback& callback) { 416 base::File::Error error = base::File::FILE_OK; 417 FileSystemOperation* operation = 418 file_system_context_->CreateFileSystemOperation(url, &error); 419 BeginOperationScoper scope; 420 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 421 if (!operation) { 422 DidFinish(handle, callback, error); 423 return handle.id; 424 } 425 PrepareForWrite(handle.id, url); 426 operation->RemoveFile( 427 url, 428 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 429 handle, callback)); 430 return handle.id; 431} 432 433OperationID FileSystemOperationRunner::RemoveDirectory( 434 const FileSystemURL& url, 435 const StatusCallback& callback) { 436 base::File::Error error = base::File::FILE_OK; 437 FileSystemOperation* operation = 438 file_system_context_->CreateFileSystemOperation(url, &error); 439 BeginOperationScoper scope; 440 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 441 if (!operation) { 442 DidFinish(handle, callback, error); 443 return handle.id; 444 } 445 PrepareForWrite(handle.id, url); 446 operation->RemoveDirectory( 447 url, 448 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 449 handle, callback)); 450 return handle.id; 451} 452 453OperationID FileSystemOperationRunner::CopyFileLocal( 454 const FileSystemURL& src_url, 455 const FileSystemURL& dest_url, 456 CopyOrMoveOption option, 457 const CopyFileProgressCallback& progress_callback, 458 const StatusCallback& callback) { 459 base::File::Error error = base::File::FILE_OK; 460 FileSystemOperation* operation = 461 file_system_context_->CreateFileSystemOperation(src_url, &error); 462 BeginOperationScoper scope; 463 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 464 if (!operation) { 465 DidFinish(handle, callback, error); 466 return handle.id; 467 } 468 PrepareForRead(handle.id, src_url); 469 PrepareForWrite(handle.id, dest_url); 470 operation->CopyFileLocal( 471 src_url, dest_url, option, progress_callback, 472 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 473 handle, callback)); 474 return handle.id; 475} 476 477OperationID FileSystemOperationRunner::MoveFileLocal( 478 const FileSystemURL& src_url, 479 const FileSystemURL& dest_url, 480 CopyOrMoveOption option, 481 const StatusCallback& callback) { 482 base::File::Error error = base::File::FILE_OK; 483 FileSystemOperation* operation = 484 file_system_context_->CreateFileSystemOperation(src_url, &error); 485 BeginOperationScoper scope; 486 OperationHandle handle = BeginOperation(operation, scope.AsWeakPtr()); 487 if (!operation) { 488 DidFinish(handle, callback, error); 489 return handle.id; 490 } 491 PrepareForWrite(handle.id, src_url); 492 PrepareForWrite(handle.id, dest_url); 493 operation->MoveFileLocal( 494 src_url, dest_url, option, 495 base::Bind(&FileSystemOperationRunner::DidFinish, AsWeakPtr(), 496 handle, callback)); 497 return handle.id; 498} 499 500base::File::Error FileSystemOperationRunner::SyncGetPlatformPath( 501 const FileSystemURL& url, 502 base::FilePath* platform_path) { 503 base::File::Error error = base::File::FILE_OK; 504 scoped_ptr<FileSystemOperation> operation( 505 file_system_context_->CreateFileSystemOperation(url, &error)); 506 if (!operation.get()) 507 return error; 508 return operation->SyncGetPlatformPath(url, platform_path); 509} 510 511FileSystemOperationRunner::FileSystemOperationRunner( 512 FileSystemContext* file_system_context) 513 : file_system_context_(file_system_context) {} 514 515void FileSystemOperationRunner::DidFinish( 516 const OperationHandle& handle, 517 const StatusCallback& callback, 518 base::File::Error rv) { 519 if (handle.scope) { 520 finished_operations_.insert(handle.id); 521 base::MessageLoopProxy::current()->PostTask( 522 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidFinish, 523 AsWeakPtr(), handle, callback, rv)); 524 return; 525 } 526 callback.Run(rv); 527 FinishOperation(handle.id); 528} 529 530void FileSystemOperationRunner::DidGetMetadata( 531 const OperationHandle& handle, 532 const GetMetadataCallback& callback, 533 base::File::Error rv, 534 const base::File::Info& file_info) { 535 if (handle.scope) { 536 finished_operations_.insert(handle.id); 537 base::MessageLoopProxy::current()->PostTask( 538 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidGetMetadata, 539 AsWeakPtr(), handle, callback, rv, file_info)); 540 return; 541 } 542 callback.Run(rv, file_info); 543 FinishOperation(handle.id); 544} 545 546void FileSystemOperationRunner::DidReadDirectory( 547 const OperationHandle& handle, 548 const ReadDirectoryCallback& callback, 549 base::File::Error rv, 550 const std::vector<DirectoryEntry>& entries, 551 bool has_more) { 552 if (handle.scope) { 553 finished_operations_.insert(handle.id); 554 base::MessageLoopProxy::current()->PostTask( 555 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidReadDirectory, 556 AsWeakPtr(), handle, callback, rv, 557 entries, has_more)); 558 return; 559 } 560 callback.Run(rv, entries, has_more); 561 if (rv != base::File::FILE_OK || !has_more) 562 FinishOperation(handle.id); 563} 564 565void FileSystemOperationRunner::DidWrite( 566 const OperationHandle& handle, 567 const WriteCallback& callback, 568 base::File::Error rv, 569 int64 bytes, 570 bool complete) { 571 if (handle.scope) { 572 finished_operations_.insert(handle.id); 573 base::MessageLoopProxy::current()->PostTask( 574 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidWrite, AsWeakPtr(), 575 handle, callback, rv, bytes, complete)); 576 return; 577 } 578 callback.Run(rv, bytes, complete); 579 if (rv != base::File::FILE_OK || complete) 580 FinishOperation(handle.id); 581} 582 583void FileSystemOperationRunner::DidOpenFile( 584 const OperationHandle& handle, 585 const OpenFileCallback& callback, 586 base::File file, 587 const base::Closure& on_close_callback) { 588 if (handle.scope) { 589 finished_operations_.insert(handle.id); 590 base::MessageLoopProxy::current()->PostTask( 591 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidOpenFile, 592 AsWeakPtr(), handle, callback, Passed(&file), 593 on_close_callback)); 594 return; 595 } 596 callback.Run(file.Pass(), on_close_callback); 597 FinishOperation(handle.id); 598} 599 600void FileSystemOperationRunner::DidCreateSnapshot( 601 const OperationHandle& handle, 602 const SnapshotFileCallback& callback, 603 base::File::Error rv, 604 const base::File::Info& file_info, 605 const base::FilePath& platform_path, 606 const scoped_refptr<storage::ShareableFileReference>& file_ref) { 607 if (handle.scope) { 608 finished_operations_.insert(handle.id); 609 base::MessageLoopProxy::current()->PostTask( 610 FROM_HERE, base::Bind(&FileSystemOperationRunner::DidCreateSnapshot, 611 AsWeakPtr(), handle, callback, rv, file_info, 612 platform_path, file_ref)); 613 return; 614 } 615 callback.Run(rv, file_info, platform_path, file_ref); 616 FinishOperation(handle.id); 617} 618 619void FileSystemOperationRunner::OnCopyProgress( 620 const OperationHandle& handle, 621 const CopyProgressCallback& callback, 622 FileSystemOperation::CopyProgressType type, 623 const FileSystemURL& source_url, 624 const FileSystemURL& dest_url, 625 int64 size) { 626 if (handle.scope) { 627 base::MessageLoopProxy::current()->PostTask( 628 FROM_HERE, base::Bind( 629 &FileSystemOperationRunner::OnCopyProgress, 630 AsWeakPtr(), handle, callback, type, source_url, dest_url, size)); 631 return; 632 } 633 callback.Run(type, source_url, dest_url, size); 634} 635 636void FileSystemOperationRunner::PrepareForWrite(OperationID id, 637 const FileSystemURL& url) { 638 if (file_system_context_->GetUpdateObservers(url.type())) { 639 file_system_context_->GetUpdateObservers(url.type())->Notify( 640 &FileUpdateObserver::OnStartUpdate, MakeTuple(url)); 641 } 642 write_target_urls_[id].insert(url); 643} 644 645void FileSystemOperationRunner::PrepareForRead(OperationID id, 646 const FileSystemURL& url) { 647 if (file_system_context_->GetAccessObservers(url.type())) { 648 file_system_context_->GetAccessObservers(url.type())->Notify( 649 &FileAccessObserver::OnAccess, MakeTuple(url)); 650 } 651} 652 653FileSystemOperationRunner::OperationHandle 654FileSystemOperationRunner::BeginOperation( 655 FileSystemOperation* operation, 656 base::WeakPtr<BeginOperationScoper> scope) { 657 OperationHandle handle; 658 handle.id = operations_.Add(operation); 659 handle.scope = scope; 660 return handle; 661} 662 663void FileSystemOperationRunner::FinishOperation(OperationID id) { 664 OperationToURLSet::iterator found = write_target_urls_.find(id); 665 if (found != write_target_urls_.end()) { 666 const FileSystemURLSet& urls = found->second; 667 for (FileSystemURLSet::const_iterator iter = urls.begin(); 668 iter != urls.end(); ++iter) { 669 if (file_system_context_->GetUpdateObservers(iter->type())) { 670 file_system_context_->GetUpdateObservers(iter->type())->Notify( 671 &FileUpdateObserver::OnEndUpdate, MakeTuple(*iter)); 672 } 673 } 674 write_target_urls_.erase(found); 675 } 676 677 // IDMap::Lookup fails if the operation is NULL, so we don't check 678 // operations_.Lookup(id) here. 679 680 operations_.Remove(id); 681 finished_operations_.erase(id); 682 683 // Dispatch stray cancel callback if exists. 684 std::map<OperationID, StatusCallback>::iterator found_cancel = 685 stray_cancel_callbacks_.find(id); 686 if (found_cancel != stray_cancel_callbacks_.end()) { 687 // This cancel has been requested after the operation has finished, 688 // so report that we failed to stop it. 689 found_cancel->second.Run(base::File::FILE_ERROR_INVALID_OPERATION); 690 stray_cancel_callbacks_.erase(found_cancel); 691 } 692} 693 694} // namespace storage 695