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