1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_ 6 #define CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_ 7 8 #include "base/files/file_path.h" 9 #include "base/memory/weak_ptr.h" 10 #include "base/threading/sequence_bound.h" 11 #include "components/services/storage/public/mojom/native_file_system_context.mojom.h" 12 #include "content/browser/blob_storage/chrome_blob_storage_context.h" 13 #include "content/browser/native_file_system/file_system_chooser.h" 14 #include "content/common/content_export.h" 15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/native_file_system_entry_factory.h" 17 #include "content/public/browser/native_file_system_permission_context.h" 18 #include "mojo/public/cpp/bindings/pending_receiver.h" 19 #include "mojo/public/cpp/bindings/pending_remote.h" 20 #include "mojo/public/cpp/bindings/receiver_set.h" 21 #include "mojo/public/cpp/bindings/remote.h" 22 #include "mojo/public/cpp/bindings/unique_receiver_set.h" 23 #include "storage/browser/file_system/file_system_url.h" 24 #include "third_party/blink/public/mojom/native_file_system/native_file_system_file_writer.mojom.h" 25 #include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom.h" 26 #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" 27 28 namespace storage { 29 class FileSystemContext; 30 class FileSystemOperationRunner; 31 } // namespace storage 32 33 namespace content { 34 class NativeFileSystemFileHandleImpl; 35 class NativeFileSystemDirectoryHandleImpl; 36 class NativeFileSystemTransferTokenImpl; 37 class StoragePartitionImpl; 38 39 // This is the browser side implementation of the 40 // NativeFileSystemManager mojom interface. This is the main entry point for 41 // the native file system API in the browser process.Instances of this class are 42 // owned by StoragePartitionImpl. 43 // 44 // This class owns all the NativeFileSystemFileHandleImpl, 45 // NativeFileSystemDirectoryHandleImpl and NativeFileSystemTransferTokenImpl 46 // instances for a specific storage partition. 47 // 48 // This class is not thread safe, it must be constructed and used on the UI 49 // thread only. 50 class CONTENT_EXPORT NativeFileSystemManagerImpl 51 : public NativeFileSystemEntryFactory, 52 public blink::mojom::NativeFileSystemManager, 53 public storage::mojom::NativeFileSystemContext { 54 public: 55 using BindingContext = NativeFileSystemEntryFactory::BindingContext; 56 57 // State that is shared between handles that are derived from each other. 58 // Handles that are created through ChooseEntries or GetSandboxedFileSystem 59 // get new values for these properties, while any handles derived from those 60 // (i.e. children of a directory) will inherit these properties from their 61 // parent. 62 struct CONTENT_EXPORT SharedHandleState { 63 SharedHandleState( 64 scoped_refptr<NativeFileSystemPermissionGrant> read_grant, 65 scoped_refptr<NativeFileSystemPermissionGrant> write_grant, 66 storage::IsolatedContext::ScopedFSHandle file_system); 67 SharedHandleState(const SharedHandleState& other); 68 ~SharedHandleState(); 69 70 // Should never be null. These are the read and write permissions for this 71 // handle. 72 const scoped_refptr<NativeFileSystemPermissionGrant> read_grant; 73 const scoped_refptr<NativeFileSystemPermissionGrant> write_grant; 74 // Can be empty, if this handle is not backed by an isolated file system. 75 const storage::IsolatedContext::ScopedFSHandle file_system; 76 }; 77 78 // The caller is responsible for ensuring that |permission_context| outlives 79 // this instance. 80 NativeFileSystemManagerImpl( 81 scoped_refptr<storage::FileSystemContext> context, 82 scoped_refptr<ChromeBlobStorageContext> blob_context, 83 NativeFileSystemPermissionContext* permission_context, 84 bool off_the_record); 85 86 void BindReceiver( 87 const BindingContext& binding_context, 88 mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver); 89 90 void BindInternalsReceiver( 91 mojo::PendingReceiver<storage::mojom::NativeFileSystemContext> receiver); 92 93 // blink::mojom::NativeFileSystemManager: 94 void GetSandboxedFileSystem(GetSandboxedFileSystemCallback callback) override; 95 void ChooseEntries( 96 blink::mojom::ChooseFileSystemEntryType type, 97 std::vector<blink::mojom::ChooseFileSystemEntryAcceptsOptionPtr> accepts, 98 bool include_accepts_all, 99 ChooseEntriesCallback callback) override; 100 void GetFileHandleFromToken( 101 mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, 102 mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> 103 file_handle_receiver) override; 104 void GetDirectoryHandleFromToken( 105 mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, 106 mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> 107 directory_handle_receiver) override; 108 109 // storage::mojom::NativeFileSystemContext: 110 void SerializeHandle( 111 mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, 112 SerializeHandleCallback callback) override; 113 void DeserializeHandle( 114 const url::Origin& origin, 115 const std::vector<uint8_t>& bits, 116 mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) 117 override; 118 119 // NativeFileSystemEntryFactory: 120 blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath( 121 const BindingContext& binding_context, 122 const base::FilePath& file_path) override; 123 blink::mojom::NativeFileSystemEntryPtr CreateDirectoryEntryFromPath( 124 const BindingContext& binding_context, 125 const base::FilePath& directory_path) override; 126 127 // Same as CreateFileEntryFromPath, except informs the permission context that 128 // the returned entry should be writable, because this entry was the result of 129 // a "save" operation. 130 blink::mojom::NativeFileSystemEntryPtr CreateWritableFileEntryFromPath( 131 const BindingContext& binding_context, 132 const base::FilePath& file_path); 133 134 // Creates a new NativeFileSystemFileHandleImpl for a given url. Assumes the 135 // passed in URL is valid and represents a file. 136 mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> 137 CreateFileHandle(const BindingContext& binding_context, 138 const storage::FileSystemURL& url, 139 const SharedHandleState& handle_state); 140 141 // Creates a new NativeFileSystemDirectoryHandleImpl for a given url. Assumes 142 // the passed in URL is valid and represents a directory. 143 mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> 144 CreateDirectoryHandle(const BindingContext& context, 145 const storage::FileSystemURL& url, 146 const SharedHandleState& handle_state); 147 148 // Creates a new NativeFileSystemFileWriterImpl for a given target and 149 // swap file URLs. Assumes the passed in URLs are valid and represent files. 150 mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> 151 CreateFileWriter(const BindingContext& binding_context, 152 const storage::FileSystemURL& url, 153 const storage::FileSystemURL& swap_url, 154 const SharedHandleState& handle_state); 155 156 // Create a transfer token for a specific file or directory. 157 void CreateTransferToken( 158 const NativeFileSystemFileHandleImpl& file, 159 mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> 160 receiver); 161 void CreateTransferToken( 162 const NativeFileSystemDirectoryHandleImpl& directory, 163 mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> 164 receiver); 165 166 // Given a mojom transfer token, looks up the token in our internal list of 167 // valid tokens. Calls the callback with the found token, or nullptr if no 168 // valid token was found. 169 using ResolvedTokenCallback = 170 base::OnceCallback<void(NativeFileSystemTransferTokenImpl*)>; 171 void ResolveTransferToken( 172 mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, 173 ResolvedTokenCallback callback); 174 175 void DidResolveTransferTokenForFileHandle( 176 const BindingContext& binding_context, 177 mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> 178 file_handle_receiver, 179 NativeFileSystemTransferTokenImpl* resolved_token); 180 void DidResolveTransferTokenForDirectoryHandle( 181 const BindingContext& binding_context, 182 mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> 183 directory_handle_receiver, 184 NativeFileSystemTransferTokenImpl* resolved_token); 185 context()186 storage::FileSystemContext* context() { 187 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 188 return context_.get(); 189 } blob_context()190 ChromeBlobStorageContext* blob_context() { return blob_context_.get(); } 191 const base::SequenceBound<storage::FileSystemOperationRunner>& 192 operation_runner(); 193 permission_context()194 NativeFileSystemPermissionContext* permission_context() { 195 return permission_context_; 196 } 197 is_off_the_record()198 bool is_off_the_record() const { return off_the_record_; } 199 SetPermissionContextForTesting(NativeFileSystemPermissionContext * permission_context)200 void SetPermissionContextForTesting( 201 NativeFileSystemPermissionContext* permission_context) { 202 permission_context_ = permission_context; 203 } 204 205 // Remove |token| from |transfer_tokens_|. It is an error to try to remove a 206 // token that doesn't exist. 207 void RemoveToken(const base::UnguessableToken& token); 208 209 private: 210 friend class NativeFileSystemFileHandleImpl; 211 212 ~NativeFileSystemManagerImpl() override; 213 void DidOpenSandboxedFileSystem(const BindingContext& binding_context, 214 GetSandboxedFileSystemCallback callback, 215 const GURL& root, 216 const std::string& filesystem_name, 217 base::File::Error result); 218 219 void DidChooseEntries(const BindingContext& binding_context, 220 const FileSystemChooser::Options& options, 221 ChooseEntriesCallback callback, 222 blink::mojom::NativeFileSystemErrorPtr result, 223 std::vector<base::FilePath> entries); 224 void DidVerifySensitiveDirectoryAccess( 225 const BindingContext& binding_context, 226 const FileSystemChooser::Options& options, 227 ChooseEntriesCallback callback, 228 std::vector<base::FilePath> entries, 229 NativeFileSystemPermissionContext::SensitiveDirectoryResult result); 230 void DidCreateOrTruncateSaveFile(const BindingContext& binding_context, 231 const base::FilePath& path, 232 ChooseEntriesCallback callback, 233 bool success); 234 void DidChooseDirectory( 235 const BindingContext& binding_context, 236 const base::FilePath& path, 237 ChooseEntriesCallback callback, 238 NativeFileSystemPermissionContext::PermissionStatus permission); 239 240 void CreateTransferTokenImpl( 241 const storage::FileSystemURL& url, 242 const SharedHandleState& handle_state, 243 bool is_directory, 244 mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> 245 receiver); 246 void DoResolveTransferToken( 247 mojo::Remote<blink::mojom::NativeFileSystemTransferToken>, 248 ResolvedTokenCallback callback, 249 const base::UnguessableToken& token); 250 251 void DidResolveForSerializeHandle( 252 SerializeHandleCallback callback, 253 NativeFileSystemTransferTokenImpl* resolved_token); 254 255 // Creates a FileSystemURL which corresponds to a FilePath and Origin. 256 struct FileSystemURLAndFSHandle { 257 storage::FileSystemURL url; 258 std::string base_name; 259 storage::IsolatedContext::ScopedFSHandle file_system; 260 }; 261 FileSystemURLAndFSHandle CreateFileSystemURLFromPath( 262 const url::Origin& origin, 263 const base::FilePath& path); 264 265 blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPathImpl( 266 const BindingContext& binding_context, 267 const base::FilePath& file_path, 268 NativeFileSystemPermissionContext::UserAction user_action); 269 270 SEQUENCE_CHECKER(sequence_checker_); 271 272 const scoped_refptr<storage::FileSystemContext> context_; 273 const scoped_refptr<ChromeBlobStorageContext> blob_context_; 274 base::SequenceBound<storage::FileSystemOperationRunner> operation_runner_; 275 NativeFileSystemPermissionContext* permission_context_; 276 277 // All the mojo receivers for this NativeFileSystemManager itself. Keeps 278 // track of associated origin and other state as well to not have to rely on 279 // the renderer passing that in, and to be able to do security checks around 280 // transferability etc. 281 mojo::ReceiverSet<blink::mojom::NativeFileSystemManager, BindingContext> 282 receivers_; 283 284 mojo::ReceiverSet<storage::mojom::NativeFileSystemContext> 285 internals_receivers_; 286 287 // All the receivers for file and directory handles that have references to 288 // them. 289 mojo::UniqueReceiverSet<blink::mojom::NativeFileSystemFileHandle> 290 file_receivers_; 291 mojo::UniqueReceiverSet<blink::mojom::NativeFileSystemDirectoryHandle> 292 directory_receivers_; 293 mojo::UniqueReceiverSet<blink::mojom::NativeFileSystemFileWriter> 294 writer_receivers_; 295 296 bool off_the_record_; 297 298 // NativeFileSystemTransferTokenImpl owns a Transfer token receiver and is 299 // removed from this map when the mojo connection is closed. 300 std::map<base::UnguessableToken, 301 std::unique_ptr<NativeFileSystemTransferTokenImpl>> 302 transfer_tokens_; 303 304 base::WeakPtrFactory<NativeFileSystemManagerImpl> weak_factory_{this}; 305 DISALLOW_COPY_AND_ASSIGN(NativeFileSystemManagerImpl); 306 }; 307 308 } // namespace content 309 310 #endif // CONTENT_BROWSER_NATIVE_FILE_SYSTEM_NATIVE_FILE_SYSTEM_MANAGER_IMPL_H_ 311