-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrecursive_delete_operation.h
135 lines (108 loc) · 5.48 KB
/
recursive_delete_operation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SMBFS_RECURSIVE_DELETE_OPERATION_H_
#define SMBFS_RECURSIVE_DELETE_OPERATION_H_
#include <libsmbclient.h>
#include <list>
#include <string>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/memory/weak_ptr.h>
#include <base/threading/thread_task_runner_handle.h>
#include <gtest/gtest_prod.h>
#include "smbfs/mojom/smbfs.mojom.h"
#include "smbfs/samba_interface.h"
namespace smbfs {
class SmbFilesystem;
// Recursively deletes all nodes (files and sub-directories) under a given
// |root_path| by doing a post-order DFT of the directory tree and spreading
// I/O calls out over multiple tasks. |completion_callback| is called once the
// operation succeeds or fails.
//
// This class must be created, used and destroyed on the same thread.
class RecursiveDeleteOperation {
public:
using CompletionCallback =
base::OnceCallback<void(mojom::DeleteRecursivelyError)>;
// |base_share_path| is a fully-qualified SMB share path *without* the
// trailing slash (ie. smb://server/share) and |root_path| should be the
// absolute path, within that share, to the directory being deleted (ie.
// /delete/this/dir).
RecursiveDeleteOperation(SambaInterface* samba_impl,
const std::string& base_share_path,
const base::FilePath& root_path,
CompletionCallback completion_callback);
RecursiveDeleteOperation(const RecursiveDeleteOperation&) = delete;
RecursiveDeleteOperation& operator=(const RecursiveDeleteOperation&) = delete;
// Start deletion from |root_path_|, which may be a file or directory.
void Start();
protected:
// Helper for unit tests.
void SetSambaInterface(SambaInterface* samba_impl);
private:
// Multiple methods can serve as ContinuationCallbacks (ie. Finished(),
// ProcessDirectoryEntries()). The overall operation is aborted whenever the
// parameter to this callback is false.
using ContinuationCallback = base::OnceCallback<void(bool)>;
FRIEND_TEST(RecursiveDeleteOperationTest, DeleteFile);
FRIEND_TEST(RecursiveDeleteOperationTest, DeleteDirectory);
FRIEND_TEST(RecursiveDeleteOperationTest, CloseDirectory);
FRIEND_TEST(RecursiveDeleteOperationTest, GetDirectoryListing);
struct Entry {
base::FilePath path;
bool is_directory;
};
// The top-level ContinuationCallback that is called when the recursive
// deletion completes due to success or failure. It marshalls |last_error_|
// back to the |completion_callback_|.
void Finished(bool success);
// Delete the directory |dir_path| recursively. |path_removed_callback| is
// called once |dir_path| is fully removed and may be Finished() (for the
// top-level directory) or ProcessDirectoryEntries() if continuing to process
// the siblings of a |dir_path| that is a descendant of |root_path_|.
void DeleteRecursively(const base::FilePath& dir_path,
ContinuationCallback path_removed_callback);
// Process (traverse directories, delete files) all |entries| from the
// directory currently being deleted by DeleteRecursively(). For any given
// directory this method will be called multiple times, working its way
// through |entries| one-at-a-time. Each time it is called the previous entry
// is guaranteed to be completely removed unless |previous_entry_succeeded| is
// false (which aborts the entire process).
void ProcessDirectoryEntries(
std::list<Entry> entries,
ContinuationCallback processing_complete_callback,
bool previous_entry_succeeded);
// Called once all entries from a directory have been processed. If they
// were all successfully removed (|all_descendants_removed| is true) it will
// proceed to remove the directory itself. The callback may be Finished() or a
// follow-up call to ProcessDirectoryEntries() to continue processing the list
// of siblings of an entry that was itself a directory.
void OnProcessDirectoryEntriesDone(const base::FilePath& dir_path,
ContinuationCallback path_removed_callback,
bool all_descendants_removed);
// Descends into directories or removes a file.
void ProcessSingleDirectoryEntry(const Entry& entry,
ContinuationCallback entry_removed_callback);
// Build a list of Entry's to describe the contents of directory |dir_path|.
bool GetDirectoryListing(const base::FilePath& dir_path,
std::list<Entry>* const entries);
bool DeleteDirectory(const base::FilePath& dir_path);
bool DeleteFile(const base::FilePath& file_path);
bool CloseDirectory(SMBCFILE* dir);
std::string MakeSharePath(const base::FilePath& path);
// Origin/constructor thread task runner.
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_ =
base::ThreadTaskRunnerHandle::Get();
SambaInterface* samba_impl_;
const std::string base_share_path_;
const base::FilePath root_path_;
CompletionCallback completion_callback_;
// If progress is aborted at any time, the reason is stored in |last_error_|
// and marshalled back to |completion_callback_| via Finished().
mojom::DeleteRecursivelyError last_error_ =
mojom::DeleteRecursivelyError::kOk;
base::WeakPtrFactory<RecursiveDeleteOperation> weak_factory_{this};
};
} // namespace smbfs
#endif // SMBFS_RECURSIVE_DELETE_OPERATION_H_