chromium/storage/browser/file_system/copy_or_move_hook_delegate.h

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef STORAGE_BROWSER_FILE_SYSTEM_COPY_OR_MOVE_HOOK_DELEGATE_H_
#define STORAGE_BROWSER_FILE_SYSTEM_COPY_OR_MOVE_HOOK_DELEGATE_H_

#include "base/component_export.h"
#include "base/files/file.h"
#include "base/functional/callback_forward.h"
#include "base/sequence_checker.h"

namespace storage {
class FileSystemURL;

// A delegate to handle different hooks of the CopyOrMove operation.
// Its OnBegin* functions take a callback that should be called when the
// function finishes, potentially notifying of any errors during the execution
// of the function. Similarly, OnError takes a callback that is called when a
// error happens and might be used to skip the error and continue the operation.
//
// The other functions do not take a callback and can asynchronously notify of
// any progress. They are used for progress updates, etc. in
// FileSystemOperation::Copy() and Move().
//
// Note that Move() has both a same-filesystem (1) and a cross-filesystem (2)
// implementation.
// 1) Requires metadata updates. Depending on the underlying implementation:
// - we either only update the metadata of (or in other words, rename) the
// moving directory
// - or the directories are recursively copied + deleted, while the files are
// moved by having their metadata updated.
// 2) Degrades into copy + delete: each entry is copied and deleted
// recursively.
//
// When transferring files, the expected events are as follows:
// Copy: OnBeginProcessFile -> OnProgress -> ... -> OnProgress ->
//   OnEndCopy.
// Move (same-filesystem): OnBeginProcessFile -> OnEndMove.
// Move (cross-filesystem): OnBeginProcessFile -> OnProgress -> ... ->
//   OnProgress -> OnEndCopy -> OnEndRemoveSource.
//
// Here is an example callback sequence of for a copy or a cross-filesystem
// move. Suppose there are a/b/c.txt (100 bytes) and a/b/d.txt (200 bytes),
// and trying to transfer a/ to x/ recursively, then the progress update
// sequence will be (Note that for the root directory, OnBeginProcessFile is
// called instead of OnBeginProcessDirectory):
//
// OnBeginProcessFile a x/a (starting create "a" directory in x/).
// OnEndCopy a x/a (creating "a" directory in x/ is finished).
//
// OnBeginProcessDirectory a/b x/a/b (starting create "b" directory in x/a).
// OnEndCopy a/b x/a/b (creating "b" directory in x/a/ is finished).
//
// OnBeginProcessFile a/b/c.txt x/a/b/c.txt (starting to transfer "c.txt" in
//                                           x/a/b/).
// OnProgress a/b/c.txt x/a/b/c.txt 0 (The first OnProgress's `size`
//                                         should be 0).
// OnProgress a/b/c.txt x/a/b/c.txt 10
//    :
// OnProgress a/b/c.txt x/a/b/c.txt 90
// OnProgress a/b/c.txt x/a/b/c.txt 100 (The last OnProgress's `size`
//                                           should be the size of the file).
// OnEndCopy a/b/c.txt x/a/b/c.txt (transferring "c.txt" is finished).
// OnEndRemoveSource a/b/c.txt ("copy + delete" move case).
//
// OnBeginProcessFile a/b/d.txt x/a/b/d.txt (starting to transfer "d.txt" in
//                                           x/a/b).
// OnProgress a/b/d.txt x/a/b/d.txt 0 (The first OnProgress's
//                                         `size` should be 0).
// OnProgress a/b/d.txt x/a/b/d.txt 10
//    :
// OnProgress a/b/d.txt x/a/b/d.txt 190
// OnProgress a/b/d.txt x/a/b/d.txt 200 (The last OnProgress's `size`
//                                           should be the size of the file).
// OnEndCopy a/b/d.txt x/a/b/d.txt (transferring "d.txt" is finished).
// OnEndRemoveSource a/b/d.txt ("copy + delete" move case).
//
// OnEndRemoveSource a/b ("copy + delete" move case).
//
// OnEndRemoveSource a ("copy + delete" move case).
//
// Note that event sequence of a/b/c.txt and a/b/d.txt can be interlaced,
// because they can be done in parallel. Also OnProgress events are
// optional, so they may not appear. All the progress callback invocations
// should be done before StatusCallback given to the Copy is called. Especially
// if an error is found before the first progress callback invocation, the
// progress callback may NOT be invoked for the copy.
//
class COMPONENT_EXPORT(STORAGE_BROWSER) CopyOrMoveHookDelegate {};

}  // namespace storage

#endif  // STORAGE_BROWSER_FILE_SYSTEM_COPY_OR_MOVE_HOOK_DELEGATE_H_