Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / fileapi / recursive_operation_delegate.cc
blob5ec089989634b6c4ed871b620fda10d54e96d88f
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.
5 #include "webkit/fileapi/recursive_operation_delegate.h"
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"
12 namespace fileapi {
14 namespace {
15 // Don't start too many inflight operations.
16 const int kMaxInflightOperations = 5;
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) {
27 RecursiveOperationDelegate::~RecursiveOperationDelegate() {
30 void RecursiveOperationDelegate::StartRecursiveOperation(
31 const FileSystemURL& root,
32 const StatusCallback& callback) {
33 callback_ = callback;
34 pending_directories_.push(root);
35 ProcessNextDirectory();
38 LocalFileSystemOperation* RecursiveOperationDelegate::NewNestedOperation() {
39 return operation_->CreateNestedOperation();
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;
50 FileSystemURL url = pending_directories_.front();
51 pending_directories_.pop();
52 inflight_operations_++;
53 ProcessDirectory(
54 url, base::Bind(&RecursiveOperationDelegate::DidProcessDirectory,
55 AsWeakPtr(), url));
58 void RecursiveOperationDelegate::ProcessPendingFiles() {
59 if (pending_files_.empty()) {
60 ProcessNextDirectory();
61 return;
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())));
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;
84 ProcessPendingFiles();
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;
94 NewNestedOperation()->ReadDirectory(
95 url, base::Bind(&RecursiveOperationDelegate::DidReadDirectory,
96 AsWeakPtr(), url));
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;
112 callback_.Run(error);
113 return;
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);
125 if (has_more)
126 return;
128 inflight_operations_--;
129 DCHECK_GE(inflight_operations_, 0);
130 ProcessPendingFiles();
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;
141 DidProcessFile(error);
144 } // namespace fileapi