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