| OLD | NEW |
| (Empty) |
| 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 "webkit/fileapi/recursive_operation_delegate.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "webkit/fileapi/file_system_context.h" | |
| 9 #include "webkit/fileapi/file_system_operation_context.h" | |
| 10 #include "webkit/fileapi/local_file_system_operation.h" | |
| 11 | |
| 12 namespace fileapi { | |
| 13 | |
| 14 namespace { | |
| 15 // Don't start too many inflight operations. | |
| 16 const int kMaxInflightOperations = 5; | |
| 17 } | |
| 18 | |
| 19 RecursiveOperationDelegate::RecursiveOperationDelegate( | |
| 20 FileSystemContext* file_system_context, | |
| 21 LocalFileSystemOperation* operation) | |
| 22 : file_system_context_(file_system_context), | |
| 23 operation_(operation), | |
| 24 inflight_operations_(0) { | |
| 25 } | |
| 26 | |
| 27 RecursiveOperationDelegate::~RecursiveOperationDelegate() { | |
| 28 } | |
| 29 | |
| 30 void RecursiveOperationDelegate::StartRecursiveOperation( | |
| 31 const FileSystemURL& root, | |
| 32 const StatusCallback& callback) { | |
| 33 callback_ = callback; | |
| 34 pending_directories_.push(root); | |
| 35 ProcessNextDirectory(); | |
| 36 } | |
| 37 | |
| 38 LocalFileSystemOperation* RecursiveOperationDelegate::NewNestedOperation() { | |
| 39 return operation_->CreateNestedOperation(); | |
| 40 } | |
| 41 | |
| 42 void RecursiveOperationDelegate::ProcessNextDirectory() { | |
| 43 DCHECK(pending_files_.empty()); | |
| 44 if (inflight_operations_ > 0) | |
| 45 return; | |
| 46 if (pending_directories_.empty()) { | |
| 47 callback_.Run(base::PLATFORM_FILE_OK); | |
| 48 return; | |
| 49 } | |
| 50 FileSystemURL url = pending_directories_.front(); | |
| 51 pending_directories_.pop(); | |
| 52 inflight_operations_++; | |
| 53 ProcessDirectory( | |
| 54 url, base::Bind(&RecursiveOperationDelegate::DidProcessDirectory, | |
| 55 AsWeakPtr(), url)); | |
| 56 } | |
| 57 | |
| 58 void RecursiveOperationDelegate::ProcessPendingFiles() { | |
| 59 if (pending_files_.empty()) { | |
| 60 ProcessNextDirectory(); | |
| 61 return; | |
| 62 } | |
| 63 while (!pending_files_.empty() && | |
| 64 inflight_operations_ < kMaxInflightOperations) { | |
| 65 FileSystemURL url = pending_files_.front(); | |
| 66 pending_files_.pop(); | |
| 67 inflight_operations_++; | |
| 68 base::MessageLoopProxy::current()->PostTask( | |
| 69 FROM_HERE, | |
| 70 base::Bind(&RecursiveOperationDelegate::ProcessFile, | |
| 71 AsWeakPtr(), url, | |
| 72 base::Bind(&RecursiveOperationDelegate::DidProcessFile, | |
| 73 AsWeakPtr()))); | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 void RecursiveOperationDelegate::DidProcessFile(base::PlatformFileError error) { | |
| 78 inflight_operations_--; | |
| 79 DCHECK_GE(inflight_operations_, 0); | |
| 80 if (error != base::PLATFORM_FILE_OK) { | |
| 81 callback_.Run(error); | |
| 82 return; | |
| 83 } | |
| 84 ProcessPendingFiles(); | |
| 85 } | |
| 86 | |
| 87 void RecursiveOperationDelegate::DidProcessDirectory( | |
| 88 const FileSystemURL& url, | |
| 89 base::PlatformFileError error) { | |
| 90 if (error != base::PLATFORM_FILE_OK) { | |
| 91 callback_.Run(error); | |
| 92 return; | |
| 93 } | |
| 94 NewNestedOperation()->ReadDirectory( | |
| 95 url, base::Bind(&RecursiveOperationDelegate::DidReadDirectory, | |
| 96 AsWeakPtr(), url)); | |
| 97 } | |
| 98 | |
| 99 void RecursiveOperationDelegate::DidReadDirectory( | |
| 100 const FileSystemURL& parent, | |
| 101 base::PlatformFileError error, | |
| 102 const FileEntryList& entries, | |
| 103 bool has_more) { | |
| 104 if (error != base::PLATFORM_FILE_OK) { | |
| 105 if (error == base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY) { | |
| 106 // The given path may have been a file, so try RemoveFile now. | |
| 107 ProcessFile(parent, | |
| 108 base::Bind(&RecursiveOperationDelegate::DidTryProcessFile, | |
| 109 AsWeakPtr(), error)); | |
| 110 return; | |
| 111 } | |
| 112 callback_.Run(error); | |
| 113 return; | |
| 114 } | |
| 115 for (size_t i = 0; i < entries.size(); i++) { | |
| 116 FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL( | |
| 117 parent.origin(), | |
| 118 parent.mount_type(), | |
| 119 parent.virtual_path().Append(entries[i].name)); | |
| 120 if (entries[i].is_directory) | |
| 121 pending_directories_.push(url); | |
| 122 else | |
| 123 pending_files_.push(url); | |
| 124 } | |
| 125 if (has_more) | |
| 126 return; | |
| 127 | |
| 128 inflight_operations_--; | |
| 129 DCHECK_GE(inflight_operations_, 0); | |
| 130 ProcessPendingFiles(); | |
| 131 } | |
| 132 | |
| 133 void RecursiveOperationDelegate::DidTryProcessFile( | |
| 134 base::PlatformFileError previous_error, | |
| 135 base::PlatformFileError error) { | |
| 136 if (error == base::PLATFORM_FILE_ERROR_NOT_A_FILE) { | |
| 137 // It wasn't a file either; returns with the previous error. | |
| 138 callback_.Run(previous_error); | |
| 139 return; | |
| 140 } | |
| 141 DidProcessFile(error); | |
| 142 } | |
| 143 | |
| 144 } // namespace fileapi | |
| OLD | NEW |