12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/recursive_operation_delegate.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_runner.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace storage {
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Don't start too many inflight operations.
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxInflightOperations = 5;
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RecursiveOperationDelegate::RecursiveOperationDelegate(
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    FileSystemContext* file_system_context)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : file_system_context_(file_system_context),
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      inflight_operations_(0),
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      canceled_(false) {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RecursiveOperationDelegate::~RecursiveOperationDelegate() {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::Cancel() {
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  canceled_ = true;
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OnCancel();
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RecursiveOperationDelegate::StartRecursiveOperation(
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& root,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback) {
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_directory_stack_.empty());
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_files_.empty());
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0, inflight_operations_);
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_ = callback;
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ++inflight_operations_;
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessFile(
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      root,
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&RecursiveOperationDelegate::DidTryProcessFile,
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 AsWeakPtr(), root));
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileSystemOperationRunner* RecursiveOperationDelegate::operation_runner() {
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return file_system_context_->operation_runner();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void RecursiveOperationDelegate::OnCancel() {
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::DidTryProcessFile(
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& root,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_directory_stack_.empty());
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(pending_files_.empty());
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(1, inflight_operations_);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  --inflight_operations_;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (canceled_ || error != base::File::FILE_ERROR_NOT_A_FILE) {
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Done(error);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pending_directory_stack_.push(std::queue<FileSystemURL>());
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pending_directory_stack_.top().push(root);
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessNextDirectory();
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::ProcessNextDirectory() {
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_files_.empty());
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.top().empty());
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0, inflight_operations_);
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const FileSystemURL& url = pending_directory_stack_.top().front();
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ++inflight_operations_;
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessDirectory(
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      url,
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          &RecursiveOperationDelegate::DidProcessDirectory, AsWeakPtr()));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RecursiveOperationDelegate::DidProcessDirectory(
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_files_.empty());
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.top().empty());
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(1, inflight_operations_);
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  --inflight_operations_;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (canceled_ || error != base::File::FILE_OK) {
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Done(error);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const FileSystemURL& parent = pending_directory_stack_.top().front();
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pending_directory_stack_.push(std::queue<FileSystemURL>());
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  operation_runner()->ReadDirectory(
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      parent,
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&RecursiveOperationDelegate::DidReadDirectory,
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 AsWeakPtr(), parent));
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RecursiveOperationDelegate::DidReadDirectory(
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& parent,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error,
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileEntryList& entries,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_more) {
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0, inflight_operations_);
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (canceled_ || error != base::File::FILE_OK) {
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Done(error);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < entries.size(); i++) {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        parent.origin(),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        parent.mount_type(),
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        parent.virtual_path().Append(entries[i].name));
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (entries[i].is_directory)
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      pending_directory_stack_.top().push(url);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_files_.push(url);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Wait for next entries.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_more)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProcessPendingFiles();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::ProcessPendingFiles() {
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if ((pending_files_.empty() || canceled_) && inflight_operations_ == 0) {
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ProcessSubDirectory();
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Do not post any new tasks.
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (canceled_)
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Run ProcessFile in parallel (upto kMaxInflightOperations).
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> current_message_loop =
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::MessageLoopProxy::current();
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  while (!pending_files_.empty() &&
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)         inflight_operations_ < kMaxInflightOperations) {
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ++inflight_operations_;
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    current_message_loop->PostTask(
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        FROM_HERE,
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&RecursiveOperationDelegate::ProcessFile,
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   AsWeakPtr(), pending_files_.front(),
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   base::Bind(&RecursiveOperationDelegate::DidProcessFile,
163d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                              AsWeakPtr())));
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    pending_files_.pop();
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::DidProcessFile(
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  --inflight_operations_;
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != base::File::FILE_OK) {
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // If an error occurs, invoke Done immediately (even if there remain
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // running operations). It is because in the callback, this instance is
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // deleted.
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Done(error);
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
177d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessPendingFiles();
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::ProcessSubDirectory() {
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_files_.empty());
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(0, inflight_operations_);
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (canceled_) {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Done(base::File::FILE_ERROR_ABORT);
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!pending_directory_stack_.top().empty()) {
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // There remain some sub directories. Process them first.
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ProcessNextDirectory();
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // All subdirectories are processed.
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pending_directory_stack_.pop();
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (pending_directory_stack_.empty()) {
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // All files/directories are processed.
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Done(base::File::FILE_OK);
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.top().empty());
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ++inflight_operations_;
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  PostProcessDirectory(
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      pending_directory_stack_.top().front(),
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&RecursiveOperationDelegate::DidPostProcessDirectory,
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 AsWeakPtr()));
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void RecursiveOperationDelegate::DidPostProcessDirectory(
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(pending_files_.empty());
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.empty());
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(!pending_directory_stack_.top().empty());
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(1, inflight_operations_);
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  --inflight_operations_;
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  pending_directory_stack_.top().pop();
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (canceled_ || error != base::File::FILE_OK) {
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Done(error);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessSubDirectory();
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RecursiveOperationDelegate::Done(base::File::Error error) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (canceled_ && error == base::File::FILE_OK) {
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(base::File::FILE_ERROR_ABORT);
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    callback_.Run(error);
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace storage
240