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/copy_or_move_operation_delegate.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/base/io_buffer.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "net/base/net_errors.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/file_stream_reader.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/copy_or_move_file_validator.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_observers.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_stream_writer.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_operation_runner.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/recursive_operation_delegate.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/blob/shareable_file_reference.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace storage {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int64 kFlushIntervalInBytes = 10 << 20;  // 10MB.
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class CopyOrMoveOperationDelegate::CopyOrMoveImpl {
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~CopyOrMoveImpl() {}
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void Run(
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) = 0;
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Cancel() = 0;
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) protected:
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyOrMoveImpl() {}
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CopyOrMoveImpl);
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copies a file on a (same) file system. Just delegate the operation to
4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// |operation_runner|.
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class CopyOrMoveOnSameFileSystemImpl
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyOrMoveOnSameFileSystemImpl(
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FileSystemOperationRunner* operation_runner,
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CopyOrMoveOperationDelegate::OperationType operation_type,
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const FileSystemURL& src_url,
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const FileSystemURL& dest_url,
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CopyOrMoveOperationDelegate::CopyOrMoveOption option,
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const FileSystemOperation::CopyFileProgressCallback&
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          file_progress_callback)
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      : operation_runner_(operation_runner),
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        operation_type_(operation_type),
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        src_url_(src_url),
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        dest_url_(dest_url),
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        option_(option),
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        file_progress_callback_(file_progress_callback) {
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void Run(
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_MOVE) {
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      operation_runner_->MoveFileLocal(src_url_, dest_url_, option_, callback);
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      operation_runner_->CopyFileLocal(
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          src_url_, dest_url_, option_, file_progress_callback_, callback);
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Cancel() OVERRIDE {
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // We can do nothing for the copy/move operation on a local file system.
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Assuming the operation is quickly done, it should be ok to just wait
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // for the completion.
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunner* operation_runner_;
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyOrMoveOperationDelegate::OperationType operation_type_;
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemURL src_url_;
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemURL dest_url_;
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOnSameFileSystemImpl);
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Specifically for cross file system copy/move operation, this class creates
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// a snapshot file, validates it if necessary, runs copying process,
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// validates the created file, and removes source file for move (noop for
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// copy).
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class SnapshotCopyOrMoveImpl
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SnapshotCopyOrMoveImpl(
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      FileSystemOperationRunner* operation_runner,
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      CopyOrMoveOperationDelegate::OperationType operation_type,
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const FileSystemURL& src_url,
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const FileSystemURL& dest_url,
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CopyOrMoveOperationDelegate::CopyOrMoveOption option,
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CopyOrMoveFileValidatorFactory* validator_factory,
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const FileSystemOperation::CopyFileProgressCallback&
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          file_progress_callback)
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      : operation_runner_(operation_runner),
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        operation_type_(operation_type),
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        src_url_(src_url),
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest_url_(dest_url),
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        option_(option),
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        validator_factory_(validator_factory),
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        file_progress_callback_(file_progress_callback),
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        cancel_requested_(false),
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        weak_factory_(this) {
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void Run(
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    file_progress_callback_.Run(0);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    operation_runner_->CreateSnapshotFile(
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        src_url_,
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCreateSnapshot,
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Cancel() OVERRIDE {
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cancel_requested_ = true;
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void RunAfterCreateSnapshot(
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error,
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::File::Info& file_info,
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::FilePath& platform_path,
13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const scoped_refptr<storage::ShareableFileReference>& file_ref) {
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback.Run(error);
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // For now we assume CreateSnapshotFile always return a valid local file
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // path.
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!platform_path.empty());
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!validator_factory_) {
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // No validation is needed.
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      RunAfterPreWriteValidation(platform_path, file_info, file_ref, callback,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 base::File::FILE_OK);
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Run pre write validation.
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    PreWriteValidation(
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        platform_path,
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPreWriteValidation,
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   weak_factory_.GetWeakPtr(),
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   platform_path, file_info, file_ref, callback));
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void RunAfterPreWriteValidation(
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::FilePath& platform_path,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::File::Info& file_info,
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const scoped_refptr<storage::ShareableFileReference>& file_ref,
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback.Run(error);
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // |file_ref| is unused but necessary to keep the file alive until
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // CopyInForeignFile() is completed.
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    operation_runner_->CopyInForeignFile(
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        platform_path, dest_url_,
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterCopyInForeignFile,
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), file_info, file_ref, callback));
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void RunAfterCopyInForeignFile(
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::File::Info& file_info,
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const scoped_refptr<storage::ShareableFileReference>& file_ref,
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback.Run(error);
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    file_progress_callback_.Run(file_info.size);
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (option_ == FileSystemOperation::OPTION_NONE) {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      RunAfterTouchFile(callback, base::File::FILE_OK);
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    operation_runner_->TouchFile(
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        dest_url_, base::Time::Now() /* last_access */,
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        file_info.last_modified,
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterTouchFile,
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void RunAfterTouchFile(
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Even if TouchFile is failed, just ignore it.
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_) {
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_ERROR_ABORT);
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // |validator_| is NULL when the destination filesystem does not do
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // validation.
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!validator_) {
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // No validation is needed.
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      RunAfterPostWriteValidation(callback, base::File::FILE_OK);
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    PostWriteValidation(
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterPostWriteValidation,
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void RunAfterPostWriteValidation(
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_ERROR_ABORT);
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Failed to validate. Remove the destination file.
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      operation_runner_->Remove(
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          dest_url_, true /* recursive */,
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          base::Bind(&SnapshotCopyOrMoveImpl::DidRemoveDestForError,
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     weak_factory_.GetWeakPtr(), error, callback));
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_OK);
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_);
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Remove the source for finalizing move operation.
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    operation_runner_->Remove(
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        src_url_, true /* recursive */,
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::RunAfterRemoveSourceForMove,
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void RunAfterRemoveSourceForMove(
26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error == base::File::FILE_ERROR_NOT_FOUND)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_OK;
27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    callback.Run(error);
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void DidRemoveDestForError(
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error prior_error,
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      VLOG(1) << "Error removing destination file after validation error: "
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)              << error;
28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    callback.Run(prior_error);
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Runs pre-write validation.
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void PreWriteValidation(
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::FilePath& platform_path,
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) {
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(validator_factory_);
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    validator_.reset(
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        validator_factory_->CreateCopyOrMoveFileValidator(
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            src_url_, platform_path));
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    validator_->StartPreWriteValidation(callback);
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Runs post-write validation.
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void PostWriteValidation(
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) {
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    operation_runner_->CreateSnapshotFile(
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        dest_url_,
30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            &SnapshotCopyOrMoveImpl::PostWriteValidationAfterCreateSnapshotFile,
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            weak_factory_.GetWeakPtr(), callback));
30758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
30858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void PostWriteValidationAfterCreateSnapshotFile(
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error,
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::File::Info& file_info,
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const base::FilePath& platform_path,
31403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const scoped_refptr<storage::ShareableFileReference>& file_ref) {
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      callback.Run(error);
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(validator_);
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Note: file_ref passed here to keep the file alive until after
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // the StartPostWriteValidation operation finishes.
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    validator_->StartPostWriteValidation(
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        platform_path,
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        base::Bind(&SnapshotCopyOrMoveImpl::DidPostWriteValidation,
32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), file_ref, callback));
33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
33158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |file_ref| is unused; it is passed here to make sure the reference is
33358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // alive until after post-write validation is complete.
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void DidPostWriteValidation(
33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const scoped_refptr<storage::ShareableFileReference>& file_ref,
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    callback.Run(error);
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemOperationRunner* operation_runner_;
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyOrMoveOperationDelegate::OperationType operation_type_;
34358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemURL src_url_;
34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileSystemURL dest_url_;
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CopyOrMoveFileValidatorFactory* validator_factory_;
34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<CopyOrMoveFileValidator> validator_;
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool cancel_requested_;
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::WeakPtrFactory<SnapshotCopyOrMoveImpl> weak_factory_;
35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SnapshotCopyOrMoveImpl);
35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// The size of buffer for StreamCopyHelper.
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kReadBufferSize = 32768;
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// To avoid too many progress callbacks, it should be called less
35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// frequently than 50ms.
36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int kMinProgressCallbackInvocationSpanInMilliseconds = 50;
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Specifically for cross file system copy/move operation, this class uses
36368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// stream reader and writer for copying. Validator is not supported, so if
36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// necessary SnapshotCopyOrMoveImpl should be used.
36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class StreamCopyOrMoveImpl
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : public CopyOrMoveOperationDelegate::CopyOrMoveImpl {
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  StreamCopyOrMoveImpl(
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      FileSystemOperationRunner* operation_runner,
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FileSystemContext* file_system_context,
37168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CopyOrMoveOperationDelegate::OperationType operation_type,
37268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const FileSystemURL& src_url,
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const FileSystemURL& dest_url,
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      CopyOrMoveOperationDelegate::CopyOrMoveOption option,
37503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      scoped_ptr<storage::FileStreamReader> reader,
37668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      scoped_ptr<FileStreamWriter> writer,
37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const FileSystemOperation::CopyFileProgressCallback&
37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          file_progress_callback)
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      : operation_runner_(operation_runner),
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        file_system_context_(file_system_context),
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        operation_type_(operation_type),
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        src_url_(src_url),
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        dest_url_(dest_url),
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        option_(option),
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        reader_(reader.Pass()),
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        writer_(writer.Pass()),
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        file_progress_callback_(file_progress_callback),
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        cancel_requested_(false),
38903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        weak_factory_(this) {}
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void Run(
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback) OVERRIDE {
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Reader can be created even if the entry does not exist or the entry is
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // a directory. To check errors before destination file creation,
39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // check metadata first.
39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    operation_runner_->GetMetadata(
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        src_url_,
39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&StreamCopyOrMoveImpl::RunAfterGetMetadataForSource,
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Cancel() OVERRIDE {
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cancel_requested_ = true;
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (copy_helper_)
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      copy_helper_->Cancel();
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private:
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void NotifyOnStartUpdate(const FileSystemURL& url) {
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (file_system_context_->GetUpdateObservers(url.type())) {
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_system_context_->GetUpdateObservers(url.type())
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ->Notify(&FileUpdateObserver::OnStartUpdate, MakeTuple(url));
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void NotifyOnModifyFile(const FileSystemURL& url) {
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (file_system_context_->GetChangeObservers(url.type())) {
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_system_context_->GetChangeObservers(url.type())
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ->Notify(&FileChangeObserver::OnModifyFile, MakeTuple(url));
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void NotifyOnEndUpdate(const FileSystemURL& url) {
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (file_system_context_->GetUpdateObservers(url.type())) {
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      file_system_context_->GetUpdateObservers(url.type())
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          ->Notify(&FileUpdateObserver::OnEndUpdate, MakeTuple(url));
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void RunAfterGetMetadataForSource(
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error,
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::File::Info& file_info) {
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      callback.Run(error);
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
44068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (file_info.is_directory) {
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // If not a directory, failed with appropriate error code.
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_ERROR_NOT_A_FILE);
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
44868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // To use FileStreamWriter, we need to ensure the destination file exists.
44968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    operation_runner_->CreateFile(
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        dest_url_,
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        true /* exclusive */,
45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&StreamCopyOrMoveImpl::RunAfterCreateFileForDestination,
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   weak_factory_.GetWeakPtr(),
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   callback,
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   file_info.last_modified));
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
45768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void RunAfterCreateFileForDestination(
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const base::Time& last_modified,
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // This conversion is to return the consistent status code with
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // FileSystemFileUtil::Copy.
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (error == base::File::FILE_ERROR_NOT_A_FILE)
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      error = base::File::FILE_ERROR_INVALID_OPERATION;
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (error != base::File::FILE_OK &&
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error != base::File::FILE_ERROR_EXISTS) {
4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback.Run(error);
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (error == base::File::FILE_ERROR_EXISTS) {
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      operation_runner_->Truncate(
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          dest_url_,
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          0 /* length */,
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::Bind(&StreamCopyOrMoveImpl::RunAfterTruncateForDestination,
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     weak_factory_.GetWeakPtr(),
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     callback,
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     last_modified));
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RunAfterTruncateForDestination(
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        callback, last_modified, base::File::FILE_OK);
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void RunAfterTruncateForDestination(
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const CopyOrMoveOperationDelegate::StatusCallback& callback,
4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const base::Time& last_modified,
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::File::Error error) {
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (cancel_requested_)
4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      error = base::File::FILE_ERROR_ABORT;
4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      callback.Run(error);
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bool need_flush = dest_url_.mount_option().copy_sync_option() ==
50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                            storage::COPY_SYNC_OPTION_SYNC;
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyOnStartUpdate(dest_url_);
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK(!copy_helper_);
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    copy_helper_.reset(
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        new CopyOrMoveOperationDelegate::StreamCopyHelper(
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            reader_.Pass(), writer_.Pass(),
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            need_flush,
51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            kReadBufferSize,
51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            file_progress_callback_,
51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            base::TimeDelta::FromMilliseconds(
51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                kMinProgressCallbackInvocationSpanInMilliseconds)));
51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    copy_helper_->Run(
51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&StreamCopyOrMoveImpl::RunAfterStreamCopy,
5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback, last_modified));
51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void RunAfterStreamCopy(
52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
5214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const base::Time& last_modified,
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyOnModifyFile(dest_url_);
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NotifyOnEndUpdate(dest_url_);
5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      callback.Run(error);
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (option_ == FileSystemOperation::OPTION_NONE) {
5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      RunAfterTouchFile(callback, base::File::FILE_OK);
5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
5364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    operation_runner_->TouchFile(
5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        dest_url_, base::Time::Now() /* last_access */, last_modified,
5404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::Bind(&StreamCopyOrMoveImpl::RunAfterTouchFile,
5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void RunAfterTouchFile(
5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Even if TouchFile is failed, just ignore it.
5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_) {
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_ERROR_ABORT);
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
55368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (operation_type_ == CopyOrMoveOperationDelegate::OPERATION_COPY) {
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_OK);
55568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return;
55668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
55768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DCHECK_EQ(CopyOrMoveOperationDelegate::OPERATION_MOVE, operation_type_);
55968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
56068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Remove the source for finalizing move operation.
56168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    operation_runner_->Remove(
56268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        src_url_, false /* recursive */,
56368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        base::Bind(&StreamCopyOrMoveImpl::RunAfterRemoveForMove,
56468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
56568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
56668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
56768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void RunAfterRemoveForMove(
56868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      const CopyOrMoveOperationDelegate::StatusCallback& callback,
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::File::Error error) {
5704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (cancel_requested_)
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_ERROR_ABORT;
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error == base::File::FILE_ERROR_NOT_FOUND)
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error = base::File::FILE_OK;
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    callback.Run(error);
57568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
57668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
57768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FileSystemOperationRunner* operation_runner_;
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<FileSystemContext> file_system_context_;
57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CopyOrMoveOperationDelegate::OperationType operation_type_;
58068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FileSystemURL src_url_;
58168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FileSystemURL dest_url_;
5824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CopyOrMoveOperationDelegate::CopyOrMoveOption option_;
58303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<storage::FileStreamReader> reader_;
58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<FileStreamWriter> writer_;
58568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  FileSystemOperation::CopyFileProgressCallback file_progress_callback_;
58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<CopyOrMoveOperationDelegate::StreamCopyHelper> copy_helper_;
5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool cancel_requested_;
58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::WeakPtrFactory<StreamCopyOrMoveImpl> weak_factory_;
58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StreamCopyOrMoveImpl);
59068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
59258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace
59358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
59468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CopyOrMoveOperationDelegate::StreamCopyHelper::StreamCopyHelper(
59503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<storage::FileStreamReader> reader,
59668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_ptr<FileStreamWriter> writer,
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool need_flush,
59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int buffer_size,
59903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const FileSystemOperation::CopyFileProgressCallback& file_progress_callback,
60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const base::TimeDelta& min_progress_callback_invocation_span)
60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    : reader_(reader.Pass()),
60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      writer_(writer.Pass()),
6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      need_flush_(need_flush),
60468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      file_progress_callback_(file_progress_callback),
60568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      io_buffer_(new net::IOBufferWithSize(buffer_size)),
60668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      num_copied_bytes_(0),
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      previous_flush_offset_(0),
60868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      min_progress_callback_invocation_span_(
60968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          min_progress_callback_invocation_span),
6104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      cancel_requested_(false),
61168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      weak_factory_(this) {
61268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
61368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
61468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CopyOrMoveOperationDelegate::StreamCopyHelper::~StreamCopyHelper() {
61568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
61668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
61768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::Run(
61868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const StatusCallback& callback) {
61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  file_progress_callback_.Run(0);
62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  last_progress_callback_invocation_time_ = base::Time::Now();
62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Read(callback);
62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
62368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::Cancel() {
6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  cancel_requested_ = true;
6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::Read(
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const StatusCallback& callback) {
63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = reader_->Read(
63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      io_buffer_.get(), io_buffer_->size(),
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&StreamCopyHelper::DidRead,
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), callback));
63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DidRead(callback, result);
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
63868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::DidRead(
63968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const StatusCallback& callback, int result) {
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (cancel_requested_) {
6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_ERROR_ABORT);
6424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
64568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result < 0) {
6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(NetErrorToFileError(result));
64768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
64868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result == 0) {
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Here is the EOF.
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (need_flush_)
6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Flush(callback, true /* is_eof */);
6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else
6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback.Run(base::File::FILE_OK);
65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Write(callback, new net::DrainableIOBuffer(io_buffer_.get(), result));
66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::Write(
66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const StatusCallback& callback,
66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<net::DrainableIOBuffer> buffer) {
66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK_GT(buffer->BytesRemaining(), 0);
66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = writer_->Write(
66868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      buffer.get(), buffer->BytesRemaining(),
66968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      base::Bind(&StreamCopyHelper::DidWrite,
67068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), callback, buffer));
67168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
67268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    DidWrite(callback, buffer, result);
67368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
67468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
67568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::DidWrite(
67668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const StatusCallback& callback,
67768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_refptr<net::DrainableIOBuffer> buffer,
67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int result) {
6794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (cancel_requested_) {
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_ERROR_ABORT);
6814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
6824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
68468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (result < 0) {
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(NetErrorToFileError(result));
68668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
68868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
68968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  buffer->DidConsume(result);
69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  num_copied_bytes_ += result;
69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
69268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Check the elapsed time since last |file_progress_callback_| invocation.
69368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::Time now = base::Time::Now();
69468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (now - last_progress_callback_invocation_time_ >=
69568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      min_progress_callback_invocation_span_) {
69668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    file_progress_callback_.Run(num_copied_bytes_);
69768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    last_progress_callback_invocation_time_ = now;
69868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
69968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
70068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (buffer->BytesRemaining() > 0) {
70168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    Write(callback, buffer);
70268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
70368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
70468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (need_flush_ &&
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (num_copied_bytes_ - previous_flush_offset_) > kFlushIntervalInBytes) {
7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Flush(callback, false /* not is_eof */);
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Read(callback);
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::Flush(
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const StatusCallback& callback, bool is_eof) {
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int result = writer_->Flush(
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&StreamCopyHelper::DidFlush,
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), callback, is_eof));
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result != net::ERR_IO_PENDING)
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DidFlush(callback, is_eof, result);
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CopyOrMoveOperationDelegate::StreamCopyHelper::DidFlush(
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const StatusCallback& callback, bool is_eof, int result) {
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (cancel_requested_) {
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_ERROR_ABORT);
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  previous_flush_offset_ = num_copied_bytes_;
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_eof)
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(NetErrorToFileError(result));
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Read(callback);
73468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
73558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CopyOrMoveOperationDelegate::CopyOrMoveOperationDelegate(
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FileSystemContext* file_system_context,
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& src_root,
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& dest_root,
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OperationType operation_type,
74168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    CopyOrMoveOption option,
742d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const CopyProgressCallback& progress_callback,
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback)
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : RecursiveOperationDelegate(file_system_context),
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      src_root_(src_root),
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dest_root_(dest_root),
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      operation_type_(operation_type),
74868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      option_(option),
749d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      progress_callback_(progress_callback),
750ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      callback_(callback),
751ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      weak_factory_(this) {
75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  same_file_system_ = src_root_.IsInSameFileSystem(dest_root_);
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CopyOrMoveOperationDelegate::~CopyOrMoveOperationDelegate() {
75658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  STLDeleteElements(&running_copy_set_);
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CopyOrMoveOperationDelegate::Run() {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Not supported; this should never be called.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CopyOrMoveOperationDelegate::RunRecursively() {
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Perform light-weight checks first.
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // It is an error to try to copy/move an entry into its child.
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (same_file_system_ && src_root_.path().IsParent(dest_root_.path())) {
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (same_file_system_ && src_root_.path() == dest_root_.path()) {
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // In JS API this should return error, but we return success because Pepper
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // wants to return success and we have a code path that returns error in
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Blink for JS (http://crbug.com/329517).
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(base::File::FILE_OK);
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
781d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Start to process the source directory recursively.
782d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(kinuko): This could be too expensive for same_file_system_==true
783d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // and operation==MOVE case, probably we can just rename the root directory.
784d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // http://crbug.com/172187
785d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  StartRecursiveOperation(src_root_, callback_);
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
788d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::ProcessFile(
789d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url,
790d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const StatusCallback& callback) {
79168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!progress_callback_.is_null()) {
79268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    progress_callback_.Run(
79368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
79468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystemURL dest_url = CreateDestURL(src_url);
797d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CopyOrMoveImpl* impl = NULL;
79803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (same_file_system_ &&
79903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      (file_system_context()
80003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           ->GetFileSystemBackend(src_url.type())
80103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           ->HasInplaceCopyImplementation(src_url.type()) ||
8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       operation_type_ == OPERATION_MOVE)) {
803d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    impl = new CopyOrMoveOnSameFileSystemImpl(
80468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        operation_runner(), operation_type_, src_url, dest_url, option_,
805d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
806d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), src_url));
807d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } else {
808d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Cross filesystem case.
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error = base::File::FILE_ERROR_FAILED;
810d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CopyOrMoveFileValidatorFactory* validator_factory =
811d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        file_system_context()->GetCopyOrMoveFileValidatorFactory(
812d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            dest_root_.type(), &error);
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (error != base::File::FILE_OK) {
814d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback.Run(error);
815d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
816d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!validator_factory) {
81903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      scoped_ptr<storage::FileStreamReader> reader =
82068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          file_system_context()->CreateFileStreamReader(
8211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              src_url, 0 /* offset */, storage::kMaximumLength, base::Time());
82268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      scoped_ptr<FileStreamWriter> writer =
82368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          file_system_context()->CreateFileStreamWriter(dest_url, 0);
82468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (reader && writer) {
82568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        impl = new StreamCopyOrMoveImpl(
8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            operation_runner(),
8271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            file_system_context(),
8281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            operation_type_,
8291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            src_url,
8301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            dest_url,
8311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            option_,
8321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            reader.Pass(),
8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            writer.Pass(),
83468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
8351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       weak_factory_.GetWeakPtr(),
8361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       src_url));
83768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
83868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
83968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
84068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!impl) {
84168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      impl = new SnapshotCopyOrMoveImpl(
84268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          operation_runner(), operation_type_, src_url, dest_url, option_,
84368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          validator_factory,
84468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          base::Bind(&CopyOrMoveOperationDelegate::OnCopyFileProgress,
84568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                     weak_factory_.GetWeakPtr(), src_url));
84668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
849d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Register the running task.
850d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  running_copy_set_.insert(impl);
85168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  impl->Run(base::Bind(
85268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &CopyOrMoveOperationDelegate::DidCopyOrMoveFile,
85368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      weak_factory_.GetWeakPtr(), src_url, dest_url, callback, impl));
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
856d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::ProcessDirectory(
857d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url,
858d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const StatusCallback& callback) {
859d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (src_url == src_root_) {
860d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // The src_root_ looks to be a directory.
861d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Try removing the dest_root_ to see if it exists and/or it is an
862d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // empty directory.
863d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // We do not invoke |progress_callback_| for source root, because it is
864d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // already called in ProcessFile().
865d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    operation_runner()->RemoveDirectory(
866d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        dest_root_,
867d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
868d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                   weak_factory_.GetWeakPtr(), callback));
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!progress_callback_.is_null()) {
87368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    progress_callback_.Run(
87468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FileSystemOperation::BEGIN_COPY_ENTRY, src_url, FileSystemURL(), 0);
87568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
876d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
877d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessDirectoryInternal(src_url, CreateDestURL(src_url), callback);
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
880d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::PostProcessDirectory(
881d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url,
882d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const StatusCallback& callback) {
8834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (option_ == FileSystemOperation::OPTION_NONE) {
8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    PostProcessDirectoryAfterTouchFile(
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        src_url, callback, base::File::FILE_OK);
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  operation_runner()->GetMetadata(
8904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      src_url,
8914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(
8924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata,
8934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          weak_factory_.GetWeakPtr(), src_url, callback));
8944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CopyOrMoveOperationDelegate::OnCancel() {
8974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Request to cancel all running Copy/Move file.
8984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (std::set<CopyOrMoveImpl*>::iterator iter = running_copy_set_.begin();
8994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       iter != running_copy_set_.end(); ++iter)
9004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    (*iter)->Cancel();
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
903d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::DidCopyOrMoveFile(
904d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url,
90568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const FileSystemURL& dest_url,
906a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const StatusCallback& callback,
907d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CopyOrMoveImpl* impl,
9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
909d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  running_copy_set_.erase(impl);
910d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  delete impl;
911d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
91368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    progress_callback_.Run(
91468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
91568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
916d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
91758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  callback.Run(error);
918a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
919a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
920d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot(
921d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const StatusCallback& callback,
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error == base::File::FILE_ERROR_NOT_A_DIRECTORY) {
9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_.Run(base::File::FILE_ERROR_INVALID_OPERATION);
925d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
926d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != base::File::FILE_OK &&
9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      error != base::File::FILE_ERROR_NOT_FOUND) {
929d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    callback_.Run(error);
930d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
931d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
932d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
933d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ProcessDirectoryInternal(src_root_, dest_root_, callback);
934d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
935d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
936d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::ProcessDirectoryInternal(
93758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const FileSystemURL& src_url,
93858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const FileSystemURL& dest_url,
93958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const StatusCallback& callback) {
940d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // If operation_type == Move we may need to record directories and
941d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // restore directory timestamps in the end, though it may have
942d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // negative performance impact.
943d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // See http://crbug.com/171284 for more details.
944d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  operation_runner()->CreateDirectory(
945d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      dest_url, false /* exclusive */, false /* recursive */,
946d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Bind(&CopyOrMoveOperationDelegate::DidCreateDirectory,
94768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                 weak_factory_.GetWeakPtr(), src_url, dest_url, callback));
948d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
949a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
950d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::DidCreateDirectory(
951d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url,
95268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const FileSystemURL& dest_url,
953d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const StatusCallback& callback,
9545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!progress_callback_.is_null() && error == base::File::FILE_OK) {
95668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    progress_callback_.Run(
95768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FileSystemOperation::END_COPY_ENTRY, src_url, dest_url, 0);
95868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
959a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
960d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  callback.Run(error);
961a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
962a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
9634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterGetMetadata(
9644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const FileSystemURL& src_url,
9654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const StatusCallback& callback,
9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error,
9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::File::Info& file_info) {
9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error != base::File::FILE_OK) {
9694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Ignore the error, and run post process which should run after TouchFile.
9704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    PostProcessDirectoryAfterTouchFile(
9715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        src_url, callback, base::File::FILE_OK);
9724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
9734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
9744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  operation_runner()->TouchFile(
9764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      CreateDestURL(src_url), base::Time::Now() /* last access */,
9774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      file_info.last_modified,
9784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(
9794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile,
9804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          weak_factory_.GetWeakPtr(), src_url, callback));
9814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
9824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void CopyOrMoveOperationDelegate::PostProcessDirectoryAfterTouchFile(
9844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const FileSystemURL& src_url,
9854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const StatusCallback& callback,
9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
9874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Even if the TouchFile is failed, just ignore it.
9884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (operation_type_ == OPERATION_COPY) {
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback.Run(base::File::FILE_OK);
9914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
9924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
9934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK_EQ(OPERATION_MOVE, operation_type_);
9954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // All files and subdirectories in the directory should be moved here,
9974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // so remove the source directory for finalizing move operation.
9984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  operation_runner()->Remove(
9994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      src_url, false /* recursive */,
10004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
10014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 weak_factory_.GetWeakPtr(), callback));
10024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
10034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1004d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StatusCallback& callback,
10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::File::Error error) {
10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (error == base::File::FILE_ERROR_NOT_FOUND)
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    error = base::File::FILE_OK;
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(error);
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void CopyOrMoveOperationDelegate::OnCopyFileProgress(
1013d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const FileSystemURL& src_url, int64 size) {
101468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!progress_callback_.is_null()) {
101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    progress_callback_.Run(
101668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        FileSystemOperation::PROGRESS, src_url, FileSystemURL(), size);
101768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
1018d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1019d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1020868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)FileSystemURL CopyOrMoveOperationDelegate::CreateDestURL(
10212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FileSystemURL& src_url) const {
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(src_root_.type(), src_url.type());
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(src_root_.origin(), src_url.origin());
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath relative = dest_root_.virtual_path();
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  src_root_.virtual_path().AppendRelativePath(src_url.virtual_path(),
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              &relative);
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_system_context()->CreateCrackedFileSystemURL(
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dest_root_.origin(),
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dest_root_.mount_type(),
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      relative);
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
103403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // namespace storage
1035