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_ARC_FILEAPI_ARC_FILE_SYSTEM_BRIDGE_H_
6 #define CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_FILE_SYSTEM_BRIDGE_H_
7 
8 #include <stdint.h>
9 
10 #include <list>
11 #include <map>
12 #include <memory>
13 #include <string>
14 
15 #include "base/gtest_prod_util.h"
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/observer_list.h"
19 #include "chrome/browser/chromeos/arc/fileapi/arc_select_files_handler.h"
20 #include "chrome/browser/chromeos/arc/fileapi/file_stream_forwarder.h"
21 #include "components/arc/mojom/file_system.mojom-forward.h"
22 #include "components/arc/session/connection_observer.h"
23 #include "components/keyed_service/core/keyed_service.h"
24 #include "storage/browser/file_system/watcher_manager.h"
25 
26 class BrowserContextKeyedServiceFactory;
27 class GURL;
28 class Profile;
29 
30 namespace content {
31 class BrowserContext;
32 }  // namespace content
33 
34 namespace arc {
35 
36 class ArcBridgeService;
37 
38 // This class handles file system related IPC from the ARC container.
39 class ArcFileSystemBridge
40     : public KeyedService,
41       public ConnectionObserver<mojom::FileSystemInstance>,
42       public mojom::FileSystemHost {
43  public:
44   class Observer {
45    public:
OnDocumentChanged(int64_t watcher_id,storage::WatcherManager::ChangeType type)46     virtual void OnDocumentChanged(int64_t watcher_id,
47                                    storage::WatcherManager::ChangeType type) {}
OnRootsChanged()48     virtual void OnRootsChanged() {}
49 
50    protected:
~Observer()51     virtual ~Observer() {}
52   };
53 
54   ArcFileSystemBridge(content::BrowserContext* context,
55                       ArcBridgeService* bridge_service);
56   ~ArcFileSystemBridge() override;
57 
58   // Returns the factory instance for this class.
59   static BrowserContextKeyedServiceFactory* GetFactory();
60 
61   // Returns the instance for the given BrowserContext, or nullptr if the
62   // browser |context| is not allowed to use ARC.
63   static ArcFileSystemBridge* GetForBrowserContext(
64       content::BrowserContext* context);
65   static ArcFileSystemBridge* GetForBrowserContextForTesting(
66       content::BrowserContext* context);
67 
68   // Handles a read request.
69   bool HandleReadRequest(const std::string& id,
70                          int64_t offset,
71                          int64_t size,
72                          base::ScopedFD pipe_write_end);
73 
74   // Releases resources associated with the ID.
75   bool HandleIdReleased(const std::string& id);
76 
77   // Adds an observer.
78   void AddObserver(Observer* observer);
79 
80   // Removes an observer.
81   void RemoveObserver(Observer* observer);
82 
83   // FileSystemHost overrides:
84   void GetFileName(const std::string& url,
85                    GetFileNameCallback callback) override;
86   void GetFileSize(const std::string& url,
87                    GetFileSizeCallback callback) override;
88   void GetFileType(const std::string& url,
89                    GetFileTypeCallback callback) override;
90   void OnDocumentChanged(int64_t watcher_id,
91                          storage::WatcherManager::ChangeType type) override;
92   void OnRootsChanged() override;
93   void GetVirtualFileId(const std::string& url,
94                         GetVirtualFileIdCallback callback) override;
95   void HandleIdReleased(const std::string& id,
96                         HandleIdReleasedCallback callback) override;
97   void OpenFileToRead(const std::string& url,
98                       OpenFileToReadCallback callback) override;
99   void SelectFiles(mojom::SelectFilesRequestPtr request,
100                    SelectFilesCallback callback) override;
101   void OnFileSelectorEvent(mojom::FileSelectorEventPtr event,
102                            OnFileSelectorEventCallback callback) override;
103   void GetFileSelectorElements(
104       mojom::GetFileSelectorElementsRequestPtr request,
105       GetFileSelectorElementsCallback callback) override;
106 
107   // ConnectionObserver<mojom::FileSystemInstance> overrides:
108   void OnConnectionClosed() override;
109 
110  private:
111   FRIEND_TEST_ALL_PREFIXES(ArcFileSystemBridgeTest,
112                            GetLinuxVFSPathFromExternalFileURL);
113   FRIEND_TEST_ALL_PREFIXES(ArcFileSystemBridgeTest,
114                            GetLinuxVFSPathForPathOnFileSystemType);
115 
116   using GenerateVirtualFileIdCallback =
117       base::OnceCallback<void(const base::Optional<std::string>& id)>;
118 
119   // Used to implement GetFileSize().
120   void GetFileSizeInternal(const GURL& url_decoded,
121                            GetFileSizeCallback callback);
122 
123   // Used to implement GetVirtualFileId().
124   void GetVirtualFileIdInternal(const GURL& url_decoded,
125                                 GetVirtualFileIdCallback callback);
126 
127   // Used to implement GetVirtualFileId().
128   void GenerateVirtualFileId(const GURL& url_decoded,
129                              GenerateVirtualFileIdCallback callback,
130                              int64_t size);
131 
132   // Used to implement GetVirtualFileId().
133   void OnGenerateVirtualFileId(const GURL& url_decoded,
134                                GenerateVirtualFileIdCallback callback,
135                                const base::Optional<std::string>& id);
136 
137   // Used to implement OpenFileToRead().
138   void OpenFileById(const GURL& url_decoded,
139                     OpenFileToReadCallback callback,
140                     const base::Optional<std::string>& id);
141 
142   // Used to implement OpenFileToRead().
143   void OnOpenFileById(const GURL& url_decoded,
144                       OpenFileToReadCallback callback,
145                       const std::string& id,
146                       base::ScopedFD fd);
147 
148   // Used to implement OpenFileToRead(), needs to be testable.
149   //
150   // Decode a percent-encoded externalfile: URL to an absolute path on
151   // the Linux VFS (virtual file system). This returns a non-empty path
152   // for FUSE filesystems (ie. DriveFS, SmbFs, archives) that utilise FD
153   // passing and externalfile: in file_manager::util::ConvertPathToArcUrl().
154   // Returns an empty path for Chrome's virtual filesystems that are not exposed
155   // on the Linux VFS (ie. MTP, FSP).
156   base::FilePath GetLinuxVFSPathFromExternalFileURL(Profile* const profile,
157                                                     const GURL& url);
158 
159   // Used to implement OpenFileToRead(), needs to be testable.
160   //
161   // Takes a path within the mount namespace of a specific FileSystemType and
162   // returns the path on the Linux VFS, if it exists, or an empty path
163   // otherwise.
164   base::FilePath GetLinuxVFSPathForPathOnFileSystemType(
165       Profile* const profile,
166       const base::FilePath& path,
167       storage::FileSystemType file_system_type);
168 
169   // Called when FileStreamForwarder completes read request.
170   void OnReadRequestCompleted(const std::string& id,
171                               std::list<FileStreamForwarderPtr>::iterator it,
172                               bool result);
173 
174   Profile* const profile_;
175   ArcBridgeService* const bridge_service_;  // Owned by ArcServiceManager
176   base::ObserverList<Observer>::Unchecked observer_list_;
177 
178   // Map from file descriptor IDs to requested URLs.
179   std::map<std::string, GURL> id_to_url_;
180 
181   std::list<FileStreamForwarderPtr> file_stream_forwarders_;
182 
183   std::unique_ptr<ArcSelectFilesHandlersManager> select_files_handlers_manager_;
184 
185   base::WeakPtrFactory<ArcFileSystemBridge> weak_ptr_factory_{this};
186 
187   DISALLOW_COPY_AND_ASSIGN(ArcFileSystemBridge);
188 };
189 
190 }  // namespace arc
191 
192 #endif  // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_FILE_SYSTEM_BRIDGE_H_
193