1 // Copyright 2013 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_FILE_MANAGER_VOLUME_MANAGER_H_ 6 #define CHROME_BROWSER_CHROMEOS_FILE_MANAGER_VOLUME_MANAGER_H_ 7 8 #include <map> 9 #include <memory> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/files/file.h" 15 #include "base/files/file_path.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/session/arc_session_manager_observer.h" 20 #include "chrome/browser/chromeos/drive/drive_integration_service.h" 21 #include "chrome/browser/chromeos/file_manager/documents_provider_root_manager.h" 22 #include "chrome/browser/chromeos/file_system_provider/icon_set.h" 23 #include "chrome/browser/chromeos/file_system_provider/observer.h" 24 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h" 25 #include "chrome/browser/chromeos/file_system_provider/service.h" 26 #include "chromeos/dbus/cros_disks_client.h" 27 #include "chromeos/disks/disk_mount_manager.h" 28 #include "components/keyed_service/core/keyed_service.h" 29 #include "components/prefs/pref_change_registrar.h" 30 #include "components/storage_monitor/removable_storage_observer.h" 31 #include "services/device/public/mojom/mtp_manager.mojom.h" 32 33 class Profile; 34 35 namespace chromeos { 36 class PowerManagerClient; 37 38 namespace disks { 39 class Disk; 40 } // namespace disks 41 42 } // namespace chromeos 43 44 namespace content { 45 class BrowserContext; 46 } // namespace content 47 48 namespace file_manager { 49 50 class SnapshotManager; 51 class VolumeManagerObserver; 52 53 // Identifiers for volume types managed by Chrome OS file manager. 54 enum VolumeType { 55 VOLUME_TYPE_TESTING = -1, // Used only in tests. 56 VOLUME_TYPE_GOOGLE_DRIVE = 0, 57 VOLUME_TYPE_DOWNLOADS_DIRECTORY, 58 VOLUME_TYPE_REMOVABLE_DISK_PARTITION, 59 VOLUME_TYPE_MOUNTED_ARCHIVE_FILE, 60 VOLUME_TYPE_PROVIDED, // File system provided by the FileSystemProvider API. 61 VOLUME_TYPE_MTP, 62 VOLUME_TYPE_MEDIA_VIEW, 63 VOLUME_TYPE_CROSTINI, 64 VOLUME_TYPE_ANDROID_FILES, 65 VOLUME_TYPE_DOCUMENTS_PROVIDER, 66 VOLUME_TYPE_SMB, 67 // The enum values must be kept in sync with FileManagerVolumeType in 68 // tools/metrics/histograms/enums.xml. Since enums for histograms are 69 // append-only (for keeping the number consistent across versions), new values 70 // for this enum also has to be always appended at the end (i.e., here). 71 NUM_VOLUME_TYPE, 72 }; 73 74 // Says how was the mount performed, whether due to user interaction, or 75 // automatic. User interaction includes both hardware (pluggins a USB stick) 76 // or software (mounting a ZIP archive) interaction. 77 enum MountContext { 78 MOUNT_CONTEXT_USER, 79 MOUNT_CONTEXT_AUTO, 80 MOUNT_CONTEXT_UNKNOWN 81 }; 82 83 // Source of a volume's data. 84 enum Source { SOURCE_FILE, SOURCE_DEVICE, SOURCE_NETWORK, SOURCE_SYSTEM }; 85 86 // Represents a volume (mount point) in the volume manager. Validity of the data 87 // is guaranteed by the weak pointer. Simply saying, the weak pointer should be 88 // valid as long as the volume is mounted. 89 class Volume : public base::SupportsWeakPtr<Volume> { 90 public: 91 ~Volume(); 92 93 // Factory static methods for different volume types. 94 static std::unique_ptr<Volume> CreateForDrive( 95 const base::FilePath& drive_path); 96 static std::unique_ptr<Volume> CreateForDownloads( 97 const base::FilePath& downloads_path); 98 static std::unique_ptr<Volume> CreateForRemovable( 99 const chromeos::disks::DiskMountManager::MountPointInfo& mount_point, 100 const chromeos::disks::Disk* disk); 101 static std::unique_ptr<Volume> CreateForProvidedFileSystem( 102 const chromeos::file_system_provider::ProvidedFileSystemInfo& 103 file_system_info, 104 MountContext mount_context); 105 static std::unique_ptr<Volume> CreateForMTP(const base::FilePath& mount_path, 106 const std::string& label, 107 bool read_only); 108 static std::unique_ptr<Volume> CreateForMediaView( 109 const std::string& root_document_id); 110 static std::unique_ptr<Volume> CreateMediaViewForTesting( 111 base::FilePath mount_path, 112 const std::string& root_document_id); 113 static std::unique_ptr<Volume> CreateForSshfsCrostini( 114 const base::FilePath& crostini_path, 115 const base::FilePath& remote_mount_path); 116 static std::unique_ptr<Volume> CreateForAndroidFiles( 117 const base::FilePath& mount_path); 118 static std::unique_ptr<Volume> CreateForDocumentsProvider( 119 const std::string& authority, 120 const std::string& root_id, 121 const std::string& document_id, 122 const std::string& title, 123 const std::string& summary, 124 const GURL& icon_url, 125 bool read_only); 126 static std::unique_ptr<Volume> CreateForSmb(const base::FilePath& mount_point, 127 const std::string display_name); 128 static std::unique_ptr<Volume> CreateForTesting( 129 const base::FilePath& path, 130 VolumeType volume_type, 131 chromeos::DeviceType device_type, 132 bool read_only, 133 const base::FilePath& device_path, 134 const std::string& drive_label, 135 const std::string& file_system_type = ""); 136 static std::unique_ptr<Volume> CreateForTesting( 137 const base::FilePath& device_path, 138 const base::FilePath& mount_path); 139 140 // Getters for all members. See below for details. volume_id()141 const std::string& volume_id() const { return volume_id_; } file_system_id()142 const std::string& file_system_id() const { return file_system_id_; } provider_id()143 const chromeos::file_system_provider::ProviderId& provider_id() const { 144 return provider_id_; 145 } source()146 Source source() const { return source_; } type()147 VolumeType type() const { return type_; } device_type()148 chromeos::DeviceType device_type() const { return device_type_; } source_path()149 const base::FilePath& source_path() const { return source_path_; } mount_path()150 const base::FilePath& mount_path() const { return mount_path_; } remote_mount_path()151 const base::FilePath& remote_mount_path() const { return remote_mount_path_; } mount_condition()152 chromeos::disks::MountCondition mount_condition() const { 153 return mount_condition_; 154 } mount_context()155 MountContext mount_context() const { return mount_context_; } storage_device_path()156 const base::FilePath& storage_device_path() const { 157 return storage_device_path_; 158 } volume_label()159 const std::string& volume_label() const { return volume_label_; } is_parent()160 bool is_parent() const { return is_parent_; } 161 // Whether the applications can write to the volume. True if not writable. 162 // For example, when write access to external storage is restricted by the 163 // policy (ExternalStorageReadOnly), is_read_only() will be true even when 164 // is_read_only_removable_device() is false. is_read_only()165 bool is_read_only() const { return is_read_only_; } 166 // Whether the device is write-protected by hardware. This field is valid 167 // only when device_type is VOLUME_TYPE_REMOVABLE_DISK_PARTITION and 168 // source is SOURCE_DEVICE. 169 // When this value is true, is_read_only() is also true. is_read_only_removable_device()170 bool is_read_only_removable_device() const { 171 return is_read_only_removable_device_; 172 } has_media()173 bool has_media() const { return has_media_; } configurable()174 bool configurable() const { return configurable_; } watchable()175 bool watchable() const { return watchable_; } file_system_type()176 const std::string& file_system_type() const { return file_system_type_; } drive_label()177 const std::string& drive_label() const { return drive_label_; } icon_set()178 const chromeos::file_system_provider::IconSet& icon_set() const { 179 return icon_set_; 180 } 181 182 private: 183 Volume(); 184 185 // The ID of the volume. 186 std::string volume_id_; 187 188 // The ID for provided file systems. If other type, then empty string. Unique 189 // per providing extension or native provider. 190 std::string file_system_id_; 191 192 // The ID of an extension or native provider providing the file system. If 193 // other type, then equal to a ProviderId of the type INVALID. 194 chromeos::file_system_provider::ProviderId provider_id_; 195 196 // The source of the volume's data. 197 Source source_; 198 199 // The type of mounted volume. 200 VolumeType type_; 201 202 // The type of device. (e.g. USB, SD card, DVD etc.) 203 chromeos::DeviceType device_type_; 204 205 // The source path of the volume. 206 // E.g.: 207 // - /home/chronos/user/Downloads/zipfile_path.zip 208 base::FilePath source_path_; 209 210 // The mount path of the volume. 211 // E.g.: 212 // - /home/chronos/user/Downloads 213 // - /media/removable/usb1 214 // - /media/archive/zip1 215 base::FilePath mount_path_; 216 217 // The path on the remote host where this volume is mounted, for crostini this 218 // is the user's homedir (/home/<username>). 219 base::FilePath remote_mount_path_; 220 221 // The mounting condition. See the enum for the details. 222 chromeos::disks::MountCondition mount_condition_; 223 224 // The context of the mount. Whether mounting was performed due to a user 225 // interaction or not. 226 MountContext mount_context_; 227 228 // Path of the storage device this device's block is a part of. 229 // (e.g. /sys/devices/pci0000:00/.../8:0:0:0/) 230 base::FilePath storage_device_path_; 231 232 // Label for the volume if the volume is either removable or a provided 233 // file system. In case of removables, if disk is a parent, then its label, 234 // else parents label (e.g. "TransMemory"). 235 std::string volume_label_; 236 237 // Is the device is a parent device (i.e. sdb rather than sdb1). 238 bool is_parent_; 239 240 // True if the volume is not writable by applications. 241 bool is_read_only_; 242 243 // True if the volume is made read_only due to its hardware. 244 // This implies is_read_only_. 245 bool is_read_only_removable_device_; 246 247 // True if the volume contains media. 248 bool has_media_; 249 250 // True if the volume is configurable. 251 bool configurable_; 252 253 // True if the volume notifies about changes via file/directory watchers. 254 bool watchable_; 255 256 // Identifier for the file system type 257 std::string file_system_type_; 258 259 // Volume icon set. 260 chromeos::file_system_provider::IconSet icon_set_; 261 262 // Device label of a physical removable device. Removable partitions 263 // belonging to the same device share the same device label. 264 std::string drive_label_; 265 266 DISALLOW_COPY_AND_ASSIGN(Volume); 267 }; 268 269 // Manages Volumes for file manager. Example of Volumes: 270 // - Drive File System. 271 // - Downloads directory. 272 // - Removable disks (volume will be created for each partition, not only one 273 // for a device). 274 // - Mounted zip archives. 275 // - Linux/Crostini file system. 276 // - Android/Arc++ file system. 277 // - File System Providers. 278 class VolumeManager : public KeyedService, 279 public arc::ArcSessionManagerObserver, 280 public drive::DriveIntegrationServiceObserver, 281 public chromeos::disks::DiskMountManager::Observer, 282 public chromeos::file_system_provider::Observer, 283 public storage_monitor::RemovableStorageObserver, 284 public DocumentsProviderRootManager::Observer { 285 public: 286 // An alternate to device::mojom::MtpManager::GetStorageInfo. 287 // Used for injecting fake MTP manager for testing in VolumeManagerTest. 288 using GetMtpStorageInfoCallback = base::RepeatingCallback<void( 289 const std::string&, 290 device::mojom::MtpManager::GetStorageInfoCallback)>; 291 292 // Callback for |RemoveSshfsCrostiniVolume|. 293 using RemoveSshfsCrostiniVolumeCallback = base::OnceCallback<void(bool)>; 294 295 VolumeManager( 296 Profile* profile, 297 drive::DriveIntegrationService* drive_integration_service, 298 chromeos::PowerManagerClient* power_manager_client, 299 chromeos::disks::DiskMountManager* disk_mount_manager, 300 chromeos::file_system_provider::Service* file_system_provider_service, 301 GetMtpStorageInfoCallback get_mtp_storage_info_callback); 302 ~VolumeManager() override; 303 304 // Returns the instance corresponding to the |context|. 305 static VolumeManager* Get(content::BrowserContext* context); 306 307 // Initializes this instance. 308 void Initialize(); 309 310 // Disposes this instance. 311 void Shutdown() override; 312 313 // Adds an observer. 314 void AddObserver(VolumeManagerObserver* observer); 315 316 // Removes the observer. 317 void RemoveObserver(VolumeManagerObserver* observer); 318 319 // Returns the information about all volumes currently mounted. The returned 320 // weak pointers are valid as long as the volumes are mounted. 321 std::vector<base::WeakPtr<Volume>> GetVolumeList(); 322 323 // Finds Volume for the given volume ID. If found, then the returned weak 324 // pointer is valid. It is invalidated as soon as the volume is removed from 325 // the volume manager. 326 base::WeakPtr<Volume> FindVolumeById(const std::string& volume_id); 327 328 // Add sshfs crostini volume mounted at specified path. 329 void AddSshfsCrostiniVolume(const base::FilePath& sshfs_mount_path, 330 const base::FilePath& remote_mount_path); 331 332 // Removes specified sshfs crostini mount. Runs |callback| with true if the 333 // mount was removed successfully or wasn't mounted to begin with. Runs 334 // |callback| with false in all other cases. 335 void RemoveSshfsCrostiniVolume(const base::FilePath& sshfs_mount_path, 336 RemoveSshfsCrostiniVolumeCallback callback); 337 338 // Removes Downloads volume used for testing. 339 void RemoveDownloadsDirectoryForTesting(); 340 341 // For testing purposes, registers a native local file system pointing to 342 // |path| with DOWNLOADS type, and adds its volume info. 343 bool RegisterDownloadsDirectoryForTesting(const base::FilePath& path); 344 345 // For testing purposes, registers a native local file system pointing to 346 // |path| with CROSTINI type, and adds its volume info. 347 bool RegisterCrostiniDirectoryForTesting(const base::FilePath& path); 348 349 // For testing purposes, registers a native local file system pointing to 350 // |path| with ANDROID_FILES type, and adds its volume info. 351 bool RegisterAndroidFilesDirectoryForTesting(const base::FilePath& path); 352 353 // For testing purposes, register a DocumentsProvider root with 354 // VOLUME_TYPE_MEDIA_VIEW, and adds its volume info 355 bool RegisterMediaViewForTesting(const std::string& root_document_id); 356 357 // For testing purposes, removes a registered native local file system 358 // pointing to |path| with ANDROID_FILES type, and removes its volume info. 359 bool RemoveAndroidFilesDirectoryForTesting(const base::FilePath& path); 360 361 // For testing purposes, adds a volume info pointing to |path|, with TESTING 362 // type. Assumes that the mount point is already registered. 363 void AddVolumeForTesting(const base::FilePath& path, 364 VolumeType volume_type, 365 chromeos::DeviceType device_type, 366 bool read_only, 367 const base::FilePath& device_path = base::FilePath(), 368 const std::string& drive_label = "", 369 const std::string& file_system_type = ""); 370 371 // For testing purposes, adds the volume info to the volume manager. 372 void AddVolumeForTesting(std::unique_ptr<Volume> volume); 373 374 void RemoveVolumeForTesting( 375 const base::FilePath& path, 376 VolumeType volume_type, 377 chromeos::DeviceType device_type, 378 bool read_only, 379 const base::FilePath& device_path = base::FilePath(), 380 const std::string& drive_label = "", 381 const std::string& file_system_type = ""); 382 383 // drive::DriveIntegrationServiceObserver overrides. 384 void OnFileSystemMounted() override; 385 void OnFileSystemBeingUnmounted() override; 386 387 // chromeos::disks::DiskMountManager::Observer overrides. 388 void OnAutoMountableDiskEvent( 389 chromeos::disks::DiskMountManager::DiskEvent event, 390 const chromeos::disks::Disk& disk) override; 391 void OnDeviceEvent(chromeos::disks::DiskMountManager::DeviceEvent event, 392 const std::string& device_path) override; 393 void OnMountEvent(chromeos::disks::DiskMountManager::MountEvent event, 394 chromeos::MountError error_code, 395 const chromeos::disks::DiskMountManager::MountPointInfo& 396 mount_info) override; 397 void OnFormatEvent(chromeos::disks::DiskMountManager::FormatEvent event, 398 chromeos::FormatError error_code, 399 const std::string& device_path, 400 const std::string& device_label) override; 401 void OnPartitionEvent(chromeos::disks::DiskMountManager::PartitionEvent event, 402 chromeos::PartitionError error_code, 403 const std::string& device_path, 404 const std::string& device_label) override; 405 void OnRenameEvent(chromeos::disks::DiskMountManager::RenameEvent event, 406 chromeos::RenameError error_code, 407 const std::string& device_path, 408 const std::string& device_label) override; 409 410 // chromeos::file_system_provider::Observer overrides. 411 void OnProvidedFileSystemMount( 412 const chromeos::file_system_provider::ProvidedFileSystemInfo& 413 file_system_info, 414 chromeos::file_system_provider::MountContext context, 415 base::File::Error error) override; 416 void OnProvidedFileSystemUnmount( 417 const chromeos::file_system_provider::ProvidedFileSystemInfo& 418 file_system_info, 419 base::File::Error error) override; 420 421 // arc::ArcSessionManagerObserver overrides. 422 void OnArcPlayStoreEnabledChanged(bool enabled) override; 423 424 // Called on change to kExternalStorageDisabled pref. 425 void OnExternalStorageDisabledChanged(); 426 427 // Called on change to kExternalStorageReadOnly pref. 428 void OnExternalStorageReadOnlyChanged(); 429 430 // RemovableStorageObserver overrides. 431 void OnRemovableStorageAttached( 432 const storage_monitor::StorageInfo& info) override; 433 void OnRemovableStorageDetached( 434 const storage_monitor::StorageInfo& info) override; 435 436 // file_manager::DocumentsProviderRootManager::Observer overrides. 437 void OnDocumentsProviderRootAdded( 438 const std::string& authority, 439 const std::string& root_id, 440 const std::string& document_id, 441 const std::string& title, 442 const std::string& summary, 443 const GURL& icon_url, 444 bool read_only, 445 const std::vector<std::string>& mime_types) override; 446 void OnDocumentsProviderRootRemoved(const std::string& authority, 447 const std::string& root_id, 448 const std::string& document_id) override; 449 450 // For SmbFs. 451 void AddSmbFsVolume(const base::FilePath& mount_point, 452 const std::string& display_name); 453 void RemoveSmbFsVolume(const base::FilePath& mount_point); 454 snapshot_manager()455 SnapshotManager* snapshot_manager() { return snapshot_manager_.get(); } 456 457 private: 458 void OnDiskMountManagerRefreshed(bool success); 459 void OnStorageMonitorInitialized(); 460 void DoAttachMtpStorage(const storage_monitor::StorageInfo& info, 461 device::mojom::MtpStorageInfoPtr mtp_storage_info); 462 void DoMountEvent(chromeos::MountError error_code, 463 std::unique_ptr<Volume> volume); 464 void DoUnmountEvent(chromeos::MountError error_code, const Volume& volume); 465 void OnExternalStorageDisabledChangedUnmountCallback( 466 std::vector<std::string> remaining_mount_paths, 467 chromeos::MountError error_code); 468 469 // Returns the path of the mount point for drive. 470 base::FilePath GetDriveMountPointPath() const; 471 472 void OnSshfsCrostiniUnmountCallback( 473 const base::FilePath& sshfs_mount_path, 474 RemoveSshfsCrostiniVolumeCallback callback, 475 chromeos::MountError error_code); 476 477 Profile* profile_; 478 drive::DriveIntegrationService* drive_integration_service_; // Not owned. 479 chromeos::disks::DiskMountManager* disk_mount_manager_; // Not owned. 480 PrefChangeRegistrar pref_change_registrar_; 481 base::ObserverList<VolumeManagerObserver>::Unchecked observers_; 482 chromeos::file_system_provider::Service* 483 file_system_provider_service_; // Not owned by this class. 484 GetMtpStorageInfoCallback get_mtp_storage_info_callback_; 485 std::map<std::string, std::unique_ptr<Volume>> mounted_volumes_; 486 std::unique_ptr<SnapshotManager> snapshot_manager_; 487 std::unique_ptr<DocumentsProviderRootManager> 488 documents_provider_root_manager_; 489 bool arc_volumes_mounted_ = false; 490 491 // Note: This should remain the last member so it'll be destroyed and 492 // invalidate its weak pointers before any other members are destroyed. 493 base::WeakPtrFactory<VolumeManager> weak_ptr_factory_{this}; 494 DISALLOW_COPY_AND_ASSIGN(VolumeManager); 495 }; 496 497 } // namespace file_manager 498 499 #endif // CHROME_BROWSER_CHROMEOS_FILE_MANAGER_VOLUME_MANAGER_H_ 500