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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
content / public / browser / file_system_access_permission_context.h [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_BROWSER_FILE_SYSTEM_ACCESS_PERMISSION_CONTEXT_H_
#define CONTENT_PUBLIC_BROWSER_FILE_SYSTEM_ACCESS_PERMISSION_CONTEXT_H_
#include <string>
#include <vector>
#if defined(UNIT_TEST)
#include <ostream>
#endif
#include "base/files/file_path.h"
#include "base/types/expected.h"
#include "content/public/browser/file_system_access_permission_grant.h"
#include "content/public/browser/file_system_access_write_item.h"
#include "content/public/browser/global_routing_id.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-forward.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.h"
#include "url/origin.h"
class GURL;
namespace storage {
class FileSystemURL;
} // namespace storage
namespace content {
class RenderFrameHost;
// These values are used in json serialization. Entries should not be
// renumbered and numeric values should never be reused.
enum class PathType {
// A path on the local file system. Files with these paths can be operated
// on by base::File.
kLocal = 0,
// A path on an "external" file system. These paths can only be accessed via
// the filesystem abstraction in //storage/browser/file_system, and a
// storage::FileSystemURL of type storage::kFileSystemTypeExternal.
// This path type should be used for paths retrieved via the `virtual_path`
// member of a ui::SelectedFileInfo struct.
kExternal = 1
};
struct PathInfo {
PathType type = PathType::kLocal;
// Full path of file or directory.
base::FilePath path;
// Display name of file or directory, must not be empty. This is usually
// path.BaseName(), but in some cases such as android content-URIs the path is
// unrelated to the display name.
std::string display_name;
PathInfo() = default;
explicit PathInfo(base::FilePath path)
: path(std::move(path)),
display_name(this->path.BaseName().AsUTF8Unsafe()) {
CHECK(!this->path.empty(), base::NotFatalUntil::M134);
CHECK(!this->display_name.empty(), base::NotFatalUntil::M134);
}
explicit PathInfo(base::FilePath::StringPieceType path)
: PathInfo(base::FilePath(path)) {
CHECK(!this->path.empty(), base::NotFatalUntil::M134);
CHECK(!this->display_name.empty(), base::NotFatalUntil::M134);
}
PathInfo(PathType type, base::FilePath path)
: type(type),
path(std::move(path)),
display_name(this->path.BaseName().AsUTF8Unsafe()) {
CHECK(!this->path.empty(), base::NotFatalUntil::M134);
CHECK(!this->display_name.empty(), base::NotFatalUntil::M134);
}
PathInfo(base::FilePath path, std::string display_name)
: path(std::move(path)), display_name(std::move(display_name)) {
CHECK(!this->path.empty(), base::NotFatalUntil::M134);
CHECK(!this->display_name.empty(), base::NotFatalUntil::M134);
}
PathInfo(PathType type, base::FilePath path, std::string display_name)
: type(type),
path(std::move(path)),
display_name(std::move(display_name)) {
CHECK(!this->path.empty(), base::NotFatalUntil::M134);
CHECK(!this->display_name.empty(), base::NotFatalUntil::M134);
}
bool operator==(const PathInfo& other) const = default;
};
// For testing only.
#if defined(UNIT_TEST)
inline std::ostream& operator<<(std::ostream& os, const PathInfo& path_info) {
return os << (int)path_info.type << ':' << path_info.path << ':'
<< path_info.display_name;
}
#endif
// Entry point to an embedder implemented permission context for the File System
// Access API. Instances of this class can be retrieved via a BrowserContext.
// All these methods must always be called on the UI thread.
class FileSystemAccessPermissionContext {
public:
// The type of action a user took that resulted in needing a permission grant
// for a particular path. This is used to signal to the permission context if
// the path was the result of a "save" operation, which an implementation can
// use to automatically grant write access to the path.
enum class UserAction {
// The path for which a permission grant is requested was the result of a
// "open" dialog. As such, only read access to files should be automatically
// granted, but read access to directories as well as write access to files
// or directories should not be granted without needing to request it.
kOpen,
// The path for which a permission grant is requested was the result of a
// "save" dialog, and as such it could make sense to return a grant that
// immediately allows write access without needing to request it.
kSave,
// The path for which a permission grant is requested was the result of
// loading a handle from storage. As such the grant should not start out
// as granted, even for read access.
kLoadFromStorage,
// The path for which a permission grant is requested was the result of a
// drag&drop operation. Read access should start out granted, but write
// access will require a prompt.
kDragAndDrop,
// The path for which a permission grant is requested was not the result of
// a user action. This is used for checking additional blocklist check of
// a path when obtaining a handle, therefore no prompt needs to be shown.
kNone,
};
// This enum helps distinguish between file or directory File System Access
// handles.
enum class HandleType { kFile, kDirectory };
using EntriesAllowedByEnterprisePolicyCallback =
base::OnceCallback<void(std::vector<PathInfo>)>;
// Returns the read permission grant to use for a particular path.
virtual scoped_refptr<FileSystemAccessPermissionGrant> GetReadPermissionGrant(
const url::Origin& origin,
const PathInfo& path_info,
HandleType handle_type,
UserAction user_action) = 0;
// Returns the permission grant to use for a particular path. This could be a
// grant that applies to more than just the path passed in, for example if a
// user has already granted write access to a directory, this method could
// return that existing grant when figuring the grant to use for a file in
// that directory.
virtual scoped_refptr<FileSystemAccessPermissionGrant>
GetWritePermissionGrant(const url::Origin& origin,
const PathInfo& path_info,
HandleType handle_type,
UserAction user_action) = 0;
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class SensitiveEntryResult {
kAllowed = 0, // Access to entry is okay.
kTryAgain = 1, // User should pick a different entry.
kAbort = 2, // Abandon entirely, as if picking was cancelled.
kMaxValue = kAbort
};
// Checks if access to the given `path` should be allowed or blocked. This is
// used to implement blocks for certain sensitive directories such as the
// "Windows" system directory, as well as the root of the "home" directory.
// For downloads ("Save as") it also checks the file extension. Calls
// `callback` with the result of the check, after potentially showing some UI
// to the user if the path is dangerous or should not be accessed.
virtual void ConfirmSensitiveEntryAccess(
const url::Origin& origin,
const PathInfo& path_info,
HandleType handle_type,
UserAction user_action,
GlobalRenderFrameHostId frame_id,
base::OnceCallback<void(SensitiveEntryResult)> callback) = 0;
enum class AfterWriteCheckResult { kAllow, kBlock };
// Runs a recently finished write operation through checks such as malware
// or other security checks to determine if the write should be allowed.
virtual void PerformAfterWriteChecks(
std::unique_ptr<FileSystemAccessWriteItem> item,
GlobalRenderFrameHostId frame_id,
base::OnceCallback<void(AfterWriteCheckResult)> callback) = 0;
// Returns whether the file type is considered dangerous. This is used to
// block file operations from creating or accessing these file types.
virtual bool IsFileTypeDangerous(const base::FilePath& path,
const url::Origin& origin) = 0;
// Returns whether the given RFH can use file picker.
virtual base::expected<void, std::string> CanShowFilePicker(
RenderFrameHost* rfh) = 0;
// Returns whether the give |origin| already allows read permission, or it is
// possible to request one. This is used to block file dialogs from being
// shown if permission won't be granted anyway.
virtual bool CanObtainReadPermission(const url::Origin& origin) = 0;
// Returns whether the give |origin| already allows write permission, or it is
// possible to request one. This is used to block save file dialogs from being
// shown if there is no need to ask for it.
virtual bool CanObtainWritePermission(const url::Origin& origin) = 0;
// Store the directory recently chosen by a file picker. This can later be
// retrieved via a call to |GetLastPickedDirectory| with the corresponding
// |origin| and |id|.
virtual void SetLastPickedDirectory(const url::Origin& origin,
const std::string& id,
const content::PathInfo& path_info) = 0;
// Returns the directory recently chosen by a file picker for a given
// |origin| and |id|.
virtual PathInfo GetLastPickedDirectory(const url::Origin& origin,
const std::string& id) = 0;
// Return the path associated with well-known directories such as "desktop"
// and "music", or a default path if the |directory| cannot be matched to a
// well-known directory. When |directory| is WellKnownDirectory.DIR_DOWNLOADS,
// |origin| is used to determine if browser-specified download directory
// should be returned instead of OS default download directory.
virtual base::FilePath GetWellKnownDirectoryPath(
blink::mojom::WellKnownDirectory directory,
const url::Origin& origin) = 0;
// Return the desired title of the file picker for the given `options`.
virtual std::u16string GetPickerTitle(
const blink::mojom::FilePickerOptionsPtr& options) = 0;
// Notifies that the underlying file or directory has been moved and updates
// permission grants accordingly.
virtual void NotifyEntryMoved(const url::Origin& origin,
const PathInfo& old_path,
const PathInfo& new_path) = 0;
// Invoked on file creation events originating from
// `window.showSaveFilePicker()`.
//
// See `FileSystemAccessEntryFactory::BindingContext`.
virtual void OnFileCreatedFromShowSaveFilePicker(
const GURL& file_picker_binding_context,
const storage::FileSystemURL& url) = 0;
// Checks the paths listed in `entries` to determine if they should be allowed
// or blocked within this context, for the given render frame host, based on
// enterprise policies. Invokes `callback` with the list of entries which are
// allowed.
virtual void CheckPathsAgainstEnterprisePolicy(
std::vector<PathInfo> entries,
GlobalRenderFrameHostId frame_id,
EntriesAllowedByEnterprisePolicyCallback callback) = 0;
protected:
virtual ~FileSystemAccessPermissionContext() = default;
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_FILE_SYSTEM_ACCESS_PERMISSION_CONTEXT_H_