1 // Copyright 2017 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 CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_FILE_SYSTEM_H_ 6 #define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_FILE_SYSTEM_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <string> 12 #include <vector> 13 14 #include "base/callback.h" 15 #include "base/files/file.h" 16 #include "base/macros.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/observer_list.h" 19 #include "base/timer/elapsed_timer.h" 20 #include "chrome/browser/chromeos/file_system_provider/abort_callback.h" 21 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h" 22 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h" 23 #include "chrome/browser/chromeos/file_system_provider/watcher.h" 24 #include "chrome/browser/chromeos/smb_client/smb_service.h" 25 #include "chrome/browser/chromeos/smb_client/smb_task_queue.h" 26 #include "chrome/browser/chromeos/smb_client/temp_file_manager.h" 27 #include "chromeos/dbus/smb_provider_client.h" 28 #include "storage/browser/file_system/async_file_util.h" 29 #include "storage/browser/file_system/watcher_manager.h" 30 #include "url/gurl.h" 31 32 namespace net { 33 class IOBuffer; 34 } // namespace net 35 36 namespace chromeos { 37 namespace smb_client { 38 39 class RequestManager; 40 41 // SMB provided file system implementation. For communication with SMB 42 // filesystems. 43 // SMB is an application level protocol used by Windows and Samba fileservers. 44 // Allows Files App to mount SMB filesystems. 45 class SmbFileSystem : public file_system_provider::ProvidedFileSystemInterface, 46 public base::SupportsWeakPtr<SmbFileSystem> { 47 public: 48 using MountIdCallback = 49 base::RepeatingCallback<int32_t(const ProvidedFileSystemInfo&)>; 50 using UnmountCallback = base::OnceCallback<base::File::Error( 51 const std::string&, 52 file_system_provider::Service::UnmountReason)>; 53 using RequestCredentialsCallback = 54 base::RepeatingCallback<void(const std::string& /* share_path */, 55 int32_t /* mount_id */, 56 base::OnceClosure /* reply */)>; 57 using RequestUpdatedSharePathCallback = 58 base::RepeatingCallback<void(const std::string& /* share_path */, 59 int32_t /* mount_id */, 60 SmbService::StartReadDirIfSuccessfulCallback 61 /* reply */)>; 62 63 SmbFileSystem( 64 const file_system_provider::ProvidedFileSystemInfo& file_system_info, 65 MountIdCallback mount_id_callback, 66 UnmountCallback unmount_callback, 67 RequestCredentialsCallback request_creds_callback, 68 RequestUpdatedSharePathCallback request_path_callback); 69 ~SmbFileSystem() override; 70 71 // ProvidedFileSystemInterface overrides. 72 file_system_provider::AbortCallback RequestUnmount( 73 storage::AsyncFileUtil::StatusCallback callback) override; 74 75 file_system_provider::AbortCallback GetMetadata( 76 const base::FilePath& entry_path, 77 ProvidedFileSystemInterface::MetadataFieldMask fields, 78 ProvidedFileSystemInterface::GetMetadataCallback callback) override; 79 80 file_system_provider::AbortCallback GetActions( 81 const std::vector<base::FilePath>& entry_paths, 82 GetActionsCallback callback) override; 83 84 file_system_provider::AbortCallback ExecuteAction( 85 const std::vector<base::FilePath>& entry_paths, 86 const std::string& action_id, 87 storage::AsyncFileUtil::StatusCallback callback) override; 88 89 file_system_provider::AbortCallback ReadDirectory( 90 const base::FilePath& directory_path, 91 storage::AsyncFileUtil::ReadDirectoryCallback callback) override; 92 93 file_system_provider::AbortCallback OpenFile( 94 const base::FilePath& file_path, 95 file_system_provider::OpenFileMode mode, 96 OpenFileCallback callback) override; 97 98 file_system_provider::AbortCallback CloseFile( 99 int file_handle, 100 storage::AsyncFileUtil::StatusCallback callback) override; 101 102 file_system_provider::AbortCallback ReadFile( 103 int file_handle, 104 net::IOBuffer* buffer, 105 int64_t offset, 106 int length, 107 ReadChunkReceivedCallback callback) override; 108 109 file_system_provider::AbortCallback CreateDirectory( 110 const base::FilePath& directory_path, 111 bool recursive, 112 storage::AsyncFileUtil::StatusCallback callback) override; 113 114 file_system_provider::AbortCallback CreateFile( 115 const base::FilePath& file_path, 116 storage::AsyncFileUtil::StatusCallback callback) override; 117 118 file_system_provider::AbortCallback DeleteEntry( 119 const base::FilePath& entry_path, 120 bool recursive, 121 storage::AsyncFileUtil::StatusCallback callback) override; 122 123 file_system_provider::AbortCallback CopyEntry( 124 const base::FilePath& source_path, 125 const base::FilePath& target_path, 126 storage::AsyncFileUtil::StatusCallback callback) override; 127 128 file_system_provider::AbortCallback MoveEntry( 129 const base::FilePath& source_path, 130 const base::FilePath& target_path, 131 storage::AsyncFileUtil::StatusCallback callback) override; 132 133 file_system_provider::AbortCallback Truncate( 134 const base::FilePath& file_path, 135 int64_t length, 136 storage::AsyncFileUtil::StatusCallback callback) override; 137 138 file_system_provider::AbortCallback WriteFile( 139 int file_handle, 140 net::IOBuffer* buffer, 141 int64_t offset, 142 int length, 143 storage::AsyncFileUtil::StatusCallback callback) override; 144 145 file_system_provider::AbortCallback AddWatcher( 146 const GURL& origin, 147 const base::FilePath& entry_path, 148 bool recursive, 149 bool persistent, 150 storage::AsyncFileUtil::StatusCallback callback, 151 storage::WatcherManager::NotificationCallback notification_callback) 152 override; 153 154 void RemoveWatcher(const GURL& origin, 155 const base::FilePath& entry_path, 156 bool recursive, 157 storage::AsyncFileUtil::StatusCallback callback) override; 158 159 const file_system_provider::ProvidedFileSystemInfo& GetFileSystemInfo() 160 const override; 161 162 file_system_provider::RequestManager* GetRequestManager() override; 163 164 file_system_provider::Watchers* GetWatchers() override; 165 166 const file_system_provider::OpenedFiles& GetOpenedFiles() const override; 167 168 void AddObserver( 169 file_system_provider::ProvidedFileSystemObserver* observer) override; 170 171 void RemoveObserver( 172 file_system_provider::ProvidedFileSystemObserver* observer) override; 173 174 void Notify( 175 const base::FilePath& entry_path, 176 bool recursive, 177 storage::WatcherManager::ChangeType change_type, 178 std::unique_ptr<file_system_provider::ProvidedFileSystemObserver::Changes> 179 changes, 180 const std::string& tag, 181 storage::AsyncFileUtil::StatusCallback callback) override; 182 183 void Configure(storage::AsyncFileUtil::StatusCallback callback) override; 184 185 base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() override; 186 187 private: 188 void Abort(OperationId operation_id); 189 190 // Calls CreateTempFileManager() and executes |task|. 191 void CreateTempFileManagerAndExecuteTask(SmbTask task); 192 193 // Initializes |temp_file_manager_| with |temp_file_manager| and executes 194 // |task|. 195 void InitTempFileManagerAndExecuteTask( 196 SmbTask task, 197 std::unique_ptr<TempFileManager> temp_file_manager); 198 199 // Calls WriteFile in SmbProviderClient. 200 file_system_provider::AbortCallback CallWriteFile( 201 int file_handle, 202 const std::vector<uint8_t>& data, 203 int64_t offset, 204 int length, 205 storage::AsyncFileUtil::StatusCallback callback); 206 207 file_system_provider::AbortCallback CreateAbortCallback( 208 OperationId operation_id); 209 210 file_system_provider::AbortCallback CreateAbortCallback(); 211 212 // Starts a copy operation to copy |source_path| to |target_path| with the 213 // OperationId |operation_id|. 214 void StartCopy(const base::FilePath& source_path, 215 const base::FilePath& target_path, 216 OperationId operation_id, 217 storage::AsyncFileUtil::StatusCallback callback); 218 219 // Continues a copy corresponding to |operation_id| and |copy_token|. 220 void ContinueCopy(OperationId operation_id, 221 int32_t copy_token, 222 storage::AsyncFileUtil::StatusCallback callback); 223 224 // Starts a ReadDirectory operation for |directory_path| with the OperationId 225 // |operation_id|. 226 void StartReadDirectory( 227 const base::FilePath& directory_path, 228 OperationId operation_id, 229 storage::AsyncFileUtil::ReadDirectoryCallback callback); 230 231 // Continues a ReadDirectory corresponding to |operation_id| and 232 // |read_dir_token|. |entries_count| and |metrics_timer| are used for metrics 233 // recording. 234 void ContinueReadDirectory( 235 OperationId operation_id, 236 int32_t read_dir_token, 237 storage::AsyncFileUtil::ReadDirectoryCallback callback, 238 int entires_count, 239 base::ElapsedTimer metrics_timer); 240 241 // Requests updated credentials for the mount. Once the credentials have been 242 // updated, |reply| is executed. 243 void RequestUpdatedCredentials(base::OnceClosure reply); 244 245 // Requests updated share path for the mount. Once the share path have been, 246 // updated, |reply| is executed. 247 void RequestUpdatedSharePath( 248 SmbService::StartReadDirIfSuccessfulCallback reply); 249 250 void HandleRequestUnmountCallback( 251 storage::AsyncFileUtil::StatusCallback callback, 252 smbprovider::ErrorType error); 253 254 void HandleRequestReadDirectoryCallback( 255 storage::AsyncFileUtil::ReadDirectoryCallback callback, 256 const base::ElapsedTimer& metrics_timer, 257 smbprovider::ErrorType error, 258 const smbprovider::DirectoryEntryListProto& entries) const; 259 260 file_system_provider::AbortCallback HandleSyncRedundantGetMetadata( 261 ProvidedFileSystemInterface::MetadataFieldMask fields, 262 ProvidedFileSystemInterface::GetMetadataCallback callback); 263 264 void HandleRequestGetMetadataEntryCallback( 265 ProvidedFileSystemInterface::MetadataFieldMask fields, 266 ProvidedFileSystemInterface::GetMetadataCallback callback, 267 smbprovider::ErrorType error, 268 const smbprovider::DirectoryEntryProto& entry) const; 269 270 void HandleRequestOpenFileCallback(OpenFileCallback callback, 271 smbprovider::ErrorType error, 272 int32_t file_id) const; 273 274 void HandleStatusCallback(storage::AsyncFileUtil::StatusCallback callback, 275 smbprovider::ErrorType error) const; 276 277 base::File::Error RunUnmountCallback( 278 const std::string& file_system_id, 279 file_system_provider::Service::UnmountReason reason); 280 281 void HandleRequestReadFileCallback(int32_t length, 282 scoped_refptr<net::IOBuffer> buffer, 283 ReadChunkReceivedCallback callback, 284 smbprovider::ErrorType error, 285 const base::ScopedFD& fd) const; 286 287 void HandleGetDeleteListCallback( 288 storage::AsyncFileUtil::StatusCallback callback, 289 OperationId operation_id, 290 smbprovider::ErrorType list_error, 291 const smbprovider::DeleteListProto& delete_list); 292 293 void HandleDeleteEntryCallback( 294 storage::AsyncFileUtil::StatusCallback callback, 295 smbprovider::ErrorType list_error, 296 bool is_last_entry, 297 smbprovider::ErrorType delete_error) const; 298 299 void HandleStartCopyCallback(storage::AsyncFileUtil::StatusCallback callback, 300 OperationId operation_id, 301 smbprovider::ErrorType error, 302 int32_t copy_token); 303 304 void HandleContinueCopyCallback( 305 storage::AsyncFileUtil::StatusCallback callback, 306 OperationId operation_id, 307 int32_t copy_token, 308 smbprovider::ErrorType error); 309 310 void HandleStartReadDirectoryCallback( 311 storage::AsyncFileUtil::ReadDirectoryCallback callback, 312 OperationId operation_id, 313 const base::FilePath& directory_path, 314 base::ElapsedTimer metrics_timer, 315 smbprovider::ErrorType error, 316 int32_t read_dir_token, 317 const smbprovider::DirectoryEntryListProto& entries); 318 319 void HandleContinueReadDirectoryCallback( 320 storage::AsyncFileUtil::ReadDirectoryCallback callback, 321 OperationId operation_id, 322 int32_t read_dir_token, 323 int entries_count, 324 base::ElapsedTimer metrics_timer, 325 smbprovider::ErrorType error, 326 const smbprovider::DirectoryEntryListProto& entries); 327 328 void ProcessReadDirectoryResults( 329 storage::AsyncFileUtil::ReadDirectoryCallback callback, 330 OperationId operation_id, 331 int32_t read_dir_token, 332 smbprovider::ErrorType error, 333 const smbprovider::DirectoryEntryListProto& entries, 334 int entries_count, 335 base::ElapsedTimer metrics_timer); 336 337 int32_t GetMountId() const; 338 339 std::string GetMountPath() const; 340 341 SmbProviderClient* GetSmbProviderClient() const; 342 base::WeakPtr<SmbProviderClient> GetWeakSmbProviderClient() const; 343 344 // Gets a new OperationId and adds |task| to the task_queue_ with it. Returns 345 // an AbortCallback to abort the newly created operation. 346 file_system_provider::AbortCallback EnqueueTaskAndGetCallback(SmbTask task); 347 348 // Adds |task| to the task_queue_ for |operation_id|. 349 void EnqueueTask(SmbTask task, OperationId operation_id); 350 351 // Gets a new OperationId and adds |task| to the task_queue_ with it. Returns 352 // the OperationId for the newly created Operation. 353 OperationId EnqueueTaskAndGetOperationId(SmbTask task); 354 355 // Check if the error can be recovered and handled to continue its original 356 // operation. Returns true if error can be handled. 357 bool IsRecoverableError(smbprovider::ErrorType error) const; 358 359 // Runs the StartReadDirectory if |should_retry_start_read_dir| is true. If 360 // false, |callback| will run instead. 361 void RetryStartReadDir(const base::FilePath& directory_path, 362 OperationId operation_id, 363 storage::AsyncFileUtil::ReadDirectoryCallback callback, 364 bool should_retry_start_read_dir); 365 366 const file_system_provider::ProvidedFileSystemInfo file_system_info_; 367 // opened_files_ is marked const since is currently unsupported. 368 const file_system_provider::OpenedFiles opened_files_; 369 370 MountIdCallback mount_id_callback_; 371 UnmountCallback unmount_callback_; 372 RequestCredentialsCallback request_creds_callback_; 373 RequestUpdatedSharePathCallback request_path_callback_; 374 std::unique_ptr<TempFileManager> temp_file_manager_; 375 mutable SmbTaskQueue task_queue_; 376 377 DISALLOW_COPY_AND_ASSIGN(SmbFileSystem); 378 }; 379 380 } // namespace smb_client 381 } // namespace chromeos 382 383 #endif // CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_FILE_SYSTEM_H_ 384