1 // Copyright 2014 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 // StorageMonitorLinux processes mount point change events, notifies listeners 6 // about the addition and deletion of media devices, and answers queries about 7 // mounted devices. 8 // StorageMonitorLinux lives on the UI thread, and uses a MtabWatcherLinux on 9 // the FILE thread to get mount point change events. 10 11 #ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_LINUX_H_ 12 #define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_LINUX_H_ 13 14 #if defined(OS_CHROMEOS) 15 #error "Use the ChromeOS-specific implementation instead." 16 #endif 17 18 #include <map> 19 #include <string> 20 21 #include "base/basictypes.h" 22 #include "base/compiler_specific.h" 23 #include "base/files/file_path.h" 24 #include "base/files/file_path_watcher.h" 25 #include "base/memory/scoped_ptr.h" 26 #include "base/memory/weak_ptr.h" 27 #include "components/storage_monitor/mtab_watcher_linux.h" 28 #include "components/storage_monitor/storage_monitor.h" 29 #include "content/public/browser/browser_thread.h" 30 31 namespace storage_monitor { 32 33 class MediaTransferProtocolDeviceObserverLinux; 34 35 class StorageMonitorLinux : public StorageMonitor, 36 public MtabWatcherLinux::Delegate { 37 public: 38 // Should only be called by browser start up code. 39 // Use StorageMonitor::GetInstance() instead. 40 // |mtab_file_path| is the path to a mtab file to watch for mount points. 41 explicit StorageMonitorLinux(const base::FilePath& mtab_file_path); 42 virtual ~StorageMonitorLinux(); 43 44 // Must be called for StorageMonitorLinux to work. 45 virtual void Init() OVERRIDE; 46 47 protected: 48 // Gets device information given a |device_path| and |mount_point|. 49 typedef base::Callback<scoped_ptr<StorageInfo>( 50 const base::FilePath& device_path, 51 const base::FilePath& mount_point)> GetDeviceInfoCallback; 52 53 void SetGetDeviceInfoCallbackForTest( 54 const GetDeviceInfoCallback& get_device_info_callback); 55 56 void SetMediaTransferProtocolManagerForTest( 57 device::MediaTransferProtocolManager* test_manager); 58 59 // MtabWatcherLinux::Delegate implementation. 60 virtual void UpdateMtab( 61 const MtabWatcherLinux::MountPointDeviceMap& new_mtab) OVERRIDE; 62 63 private: 64 // Structure to save mounted device information such as device path, unique 65 // identifier, device name and partition size. 66 struct MountPointInfo { 67 base::FilePath mount_device; 68 StorageInfo storage_info; 69 }; 70 71 // For use with scoped_ptr. 72 struct MtabWatcherLinuxDeleter { 73 void operator()(MtabWatcherLinux* mtab_watcher) { 74 content::BrowserThread::DeleteSoon(content::BrowserThread::FILE, 75 FROM_HERE, mtab_watcher); 76 } 77 }; 78 79 // Mapping of mount points to MountPointInfo. 80 typedef std::map<base::FilePath, MountPointInfo> MountMap; 81 82 // (mount point, priority) 83 // For devices that are mounted to multiple mount points, this helps us track 84 // which one we've notified system monitor about. 85 typedef std::map<base::FilePath, bool> ReferencedMountPoint; 86 87 // (mount device, map of known mount points) 88 // For each mount device, track the places it is mounted and which one (if 89 // any) we have notified system monitor about. 90 typedef std::map<base::FilePath, ReferencedMountPoint> MountPriorityMap; 91 92 // StorageMonitor implementation. 93 virtual bool GetStorageInfoForPath(const base::FilePath& path, 94 StorageInfo* device_info) const OVERRIDE; 95 virtual void EjectDevice(const std::string& device_id, 96 base::Callback<void(EjectStatus)> callback) OVERRIDE; 97 virtual device::MediaTransferProtocolManager* 98 media_transfer_protocol_manager() OVERRIDE; 99 100 // Called when the MtabWatcher has been created. 101 void OnMtabWatcherCreated(MtabWatcherLinux* watcher); 102 103 bool IsDeviceAlreadyMounted(const base::FilePath& mount_device) const; 104 105 // Assuming |mount_device| is already mounted, and it gets mounted again at 106 // |mount_point|, update the mappings. 107 void HandleDeviceMountedMultipleTimes(const base::FilePath& mount_device, 108 const base::FilePath& mount_point); 109 110 // Adds |mount_device| to the mappings and notify listeners, if any. 111 void AddNewMount(const base::FilePath& mount_device, 112 scoped_ptr<StorageInfo> storage_info); 113 114 // Mtab file that lists the mount points. 115 const base::FilePath mtab_path_; 116 117 // Callback to get device information. Set this to a custom callback for 118 // testing. 119 GetDeviceInfoCallback get_device_info_callback_; 120 121 // Mapping of relevant mount points and their corresponding mount devices. 122 // Keep in mind on Linux, a device can be mounted at multiple mount points, 123 // and multiple devices can be mounted at a mount point. 124 MountMap mount_info_map_; 125 126 // Because a device can be mounted to multiple places, we only want to 127 // notify about one of them. If (and only if) that one is unmounted, we need 128 // to notify about it's departure and notify about another one of it's mount 129 // points. 130 MountPriorityMap mount_priority_map_; 131 132 scoped_ptr<device::MediaTransferProtocolManager> 133 media_transfer_protocol_manager_; 134 scoped_ptr<MediaTransferProtocolDeviceObserverLinux> 135 media_transfer_protocol_device_observer_; 136 137 scoped_ptr<MtabWatcherLinux, MtabWatcherLinuxDeleter> mtab_watcher_; 138 139 base::WeakPtrFactory<StorageMonitorLinux> weak_ptr_factory_; 140 141 DISALLOW_COPY_AND_ASSIGN(StorageMonitorLinux); 142 }; 143 144 } // namespace storage_monitor 145 146 #endif // COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_LINUX_H_ 147