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