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