1 // Copyright 2018 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_GUEST_OS_GUEST_OS_SHARE_PATH_H_ 6 #define CHROME_BROWSER_CHROMEOS_GUEST_OS_GUEST_OS_SHARE_PATH_H_ 7 8 #include <map> 9 #include <memory> 10 #include <set> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/files/file_path.h" 15 #include "base/files/file_path_watcher.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/observer_list.h" 18 #include "base/sequenced_task_runner.h" 19 #include "chrome/browser/chromeos/crostini/crostini_manager.h" 20 #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h" 21 #include "chrome/browser/profiles/profile.h" 22 #include "chromeos/components/drivefs/drivefs_host_observer.h" 23 #include "chromeos/dbus/seneschal/seneschal_service.pb.h" 24 #include "components/keyed_service/core/keyed_service.h" 25 26 namespace guest_os { 27 28 using SuccessCallback = 29 base::OnceCallback<void(bool success, const std::string& failure_reason)>; 30 31 struct SharedPathInfo { 32 explicit SharedPathInfo(std::unique_ptr<base::FilePathWatcher> watcher, 33 const std::string& vm_name); 34 SharedPathInfo(SharedPathInfo&&); 35 ~SharedPathInfo(); 36 37 std::unique_ptr<base::FilePathWatcher> watcher; 38 std::set<std::string> vm_names; 39 }; 40 41 // Handles sharing and unsharing paths from the Chrome OS host to guest VMs via 42 // seneschal. 43 class GuestOsSharePath : public KeyedService, 44 public file_manager::VolumeManagerObserver, 45 public drivefs::DriveFsHostObserver { 46 public: 47 using SharePathCallback = 48 base::OnceCallback<void(const base::FilePath&, bool, const std::string&)>; 49 using SeneschalCallback = 50 base::RepeatingCallback<void(const std::string& operation, 51 const base::FilePath& cros_path, 52 const base::FilePath& container_path, 53 bool result, 54 const std::string& failure_reason)>; 55 class Observer { 56 public: 57 virtual void OnUnshare(const std::string& vm_name, 58 const base::FilePath& path) = 0; 59 }; 60 61 static GuestOsSharePath* GetForProfile(Profile* profile); 62 explicit GuestOsSharePath(Profile* profile); 63 ~GuestOsSharePath() override; 64 65 // KeyedService: 66 // FilePathWatchers are removed in Shutdown to ensure they are all destroyed 67 // before the service. 68 void Shutdown() override; 69 70 // Observer receives unshare events. 71 void AddObserver(Observer* obs); 72 73 // Share specified absolute |path| with vm. If |persist| is set, the path will 74 // be automatically shared at container startup. Callback receives path mapped 75 // in container, success bool and failure reason string. 76 void SharePath(const std::string& vm_name, 77 const base::FilePath& path, 78 bool persist, 79 SharePathCallback callback); 80 81 // Share specified absolute |paths| with vm. If |persist| is set, the paths 82 // will be automatically shared at container startup. Callback receives 83 // success bool and failure reason string of the first error. 84 void SharePaths(const std::string& vm_name, 85 std::vector<base::FilePath> paths, 86 bool persist, 87 SuccessCallback callback); 88 89 // Unshare specified |path| with |vm_name|. If |unpersist| is set, the path 90 // is removed from prefs, and will not be shared at container startup. 91 // Callback receives success bool and failure reason string. 92 void UnsharePath(const std::string& vm_name, 93 const base::FilePath& path, 94 bool unpersist, 95 SuccessCallback callback); 96 97 // Returns true the first time it is called on this service. 98 bool GetAndSetFirstForSession(); 99 100 // Get list of all shared paths for the specified VM. 101 std::vector<base::FilePath> GetPersistedSharedPaths( 102 const std::string& vm_name); 103 104 // Share all paths configured in prefs for the specified VM. 105 // Called at container startup. Callback is invoked once complete. 106 void SharePersistedPaths(const std::string& vm_name, 107 SuccessCallback callback); 108 109 // Save |path| into prefs for |vm_name|. 110 void RegisterPersistedPath(const std::string& vm_name, 111 const base::FilePath& path); 112 113 // Returns true if |path| or a parent is shared with |vm_name|. 114 bool IsPathShared(const std::string& vm_name, base::FilePath path) const; 115 116 // file_manager::VolumeManagerObserver 117 void OnVolumeMounted(chromeos::MountError error_code, 118 const file_manager::Volume& volume) override; 119 void OnVolumeUnmounted(chromeos::MountError error_code, 120 const file_manager::Volume& volume) override; 121 122 // drivefs::DriveFsHostObserver 123 void OnFilesChanged( 124 const std::vector<drivefs::mojom::FileChange>& changes) override; 125 126 // Registers |path| as shared with |vm_name|. Adds a FilePathWatcher to 127 // detect when the path has been deleted. If the path is deleted, we unshare 128 // the path, and remove it from prefs if it was persisted. 129 // Visible for testing. 130 void RegisterSharedPath(const std::string& vm_name, 131 const base::FilePath& path); 132 133 // Runs on UI Thread to handle when a path is deleted. 134 // Visible for testing. 135 void PathDeleted(const base::FilePath& path); 136 137 // Allow seneschal callback to be overridden for testing. set_seneschal_callback_for_testing(SeneschalCallback callback)138 void set_seneschal_callback_for_testing(SeneschalCallback callback) { 139 seneschal_callback_ = std::move(callback); 140 } 141 142 private: 143 void CallSeneschalSharePath(const std::string& vm_name, 144 const base::FilePath& path, 145 bool persist, 146 SharePathCallback callback); 147 148 void CallSeneschalUnsharePath(const std::string& vm_name, 149 const base::FilePath& path, 150 SuccessCallback callback); 151 152 void OnFileWatcherDeleted(const base::FilePath& path); 153 154 void OnVolumeMountCheck(const base::FilePath& path, bool mount_exists); 155 156 // Returns info for specified path or nullptr if not found. 157 SharedPathInfo* FindSharedPathInfo(const base::FilePath& path); 158 159 Profile* profile_; 160 // Task runner for FilePathWatchers to be created, run, and be destroyed on. 161 scoped_refptr<base::SequencedTaskRunner> file_watcher_task_runner_; 162 bool first_for_session_ = true; 163 164 // Allow seneschal callback to be overridden for testing. 165 SeneschalCallback seneschal_callback_; 166 base::ObserverList<Observer>::Unchecked observers_; 167 std::map<base::FilePath, SharedPathInfo> shared_paths_; 168 169 base::WeakPtrFactory<GuestOsSharePath> weak_ptr_factory_{this}; 170 171 DISALLOW_COPY_AND_ASSIGN(GuestOsSharePath); 172 }; // class 173 174 } // namespace guest_os 175 176 #endif // CHROME_BROWSER_CHROMEOS_GUEST_OS_GUEST_OS_SHARE_PATH_H_ 177