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#ifndef CHROMEOS_DISKS_DISK_MOUNT_MANAGER_H_
6#define CHROMEOS_DISKS_DISK_MOUNT_MANAGER_H_
7
8#include <map>
9
10#include "base/callback_forward.h"
11#include "chromeos/chromeos_export.h"
12#include "chromeos/dbus/cros_disks_client.h"
13
14namespace chromeos {
15namespace disks {
16
17// Condition of mounted filesystem.
18enum MountCondition {
19  MOUNT_CONDITION_NONE,
20  MOUNT_CONDITION_UNKNOWN_FILESYSTEM,
21  MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM,
22};
23
24// This class handles the interaction with cros-disks.
25// Other classes can add themselves as observers.
26class CHROMEOS_EXPORT DiskMountManager {
27 public:
28  // Event types passed to the observers.
29  enum DiskEvent {
30    DISK_ADDED,
31    DISK_REMOVED,
32    DISK_CHANGED,
33  };
34
35  enum DeviceEvent {
36    DEVICE_ADDED,
37    DEVICE_REMOVED,
38    DEVICE_SCANNED,
39  };
40
41  enum MountEvent {
42    MOUNTING,
43    UNMOUNTING,
44  };
45
46  enum FormatEvent {
47    FORMAT_STARTED,
48    FORMAT_COMPLETED
49  };
50
51  // Used to house an instance of each found mount device.
52  class Disk {
53   public:
54    Disk(const std::string& device_path,
55         const std::string& mount_path,
56         const std::string& system_path,
57         const std::string& file_path,
58         const std::string& device_label,
59         const std::string& drive_label,
60         const std::string& vendor_id,
61         const std::string& vendor_name,
62         const std::string& product_id,
63         const std::string& product_name,
64         const std::string& fs_uuid,
65         const std::string& system_path_prefix,
66         DeviceType device_type,
67         uint64 total_size_in_bytes,
68         bool is_parent,
69         bool is_read_only,
70         bool has_media,
71         bool on_boot_device,
72         bool on_removable_device,
73         bool is_hidden);
74    ~Disk();
75
76    // The path of the device, used by devicekit-disks.
77    // (e.g. /sys/devices/pci0000:00/.../8:0:0:0/block/sdb/sdb1)
78    const std::string& device_path() const { return device_path_; }
79
80    // The path to the mount point of this device. Will be empty if not mounted.
81    // (e.g. /media/removable/VOLUME)
82    const std::string&  mount_path() const { return mount_path_; }
83
84    // The path of the device according to the udev system.
85    // (e.g. /sys/devices/pci0000:00/.../8:0:0:0/block/sdb/sdb1)
86    const std::string& system_path() const { return system_path_; }
87
88    // The path of the device according to filesystem.
89    // (e.g. /dev/sdb)
90    const std::string& file_path() const { return file_path_; }
91
92    // Device's label.
93    const std::string& device_label() const { return device_label_; }
94
95    // If disk is a parent, then its label, else parents label.
96    // (e.g. "TransMemory")
97    const std::string& drive_label() const { return drive_label_; }
98
99    // Vendor ID of the device (e.g. "18d1").
100    const std::string& vendor_id() const { return vendor_id_; }
101
102    // Vendor name of the device (e.g. "Google Inc.").
103    const std::string& vendor_name() const { return vendor_name_; }
104
105    // Product ID of the device (e.g. "4e11").
106    const std::string& product_id() const { return product_id_; }
107
108    // Product name of the device (e.g. "Nexus One").
109    const std::string& product_name() const { return product_name_; }
110
111    // Returns the file system uuid string.
112    const std::string& fs_uuid() const { return fs_uuid_; }
113
114    // Path of the system device this device's block is a part of.
115    // (e.g. /sys/devices/pci0000:00/.../8:0:0:0/)
116    const std::string& system_path_prefix() const {
117      return system_path_prefix_;
118    }
119
120    // Device type.
121    DeviceType device_type() const { return device_type_; }
122
123    // Total size of the device in bytes.
124    uint64 total_size_in_bytes() const { return total_size_in_bytes_; }
125
126    // Is the device is a parent device (i.e. sdb rather than sdb1).
127    bool is_parent() const { return is_parent_; }
128
129    // Is the device read only.
130    bool is_read_only() const { return is_read_only_; }
131
132    // Does the device contains media.
133    bool has_media() const { return has_media_; }
134
135    // Is the device on the boot device.
136    bool on_boot_device() const { return on_boot_device_; }
137
138    // Is the device on the removable device.
139    bool on_removable_device() const { return on_removable_device_; }
140
141    // Shoud the device be shown in the UI, or automounted.
142    bool is_hidden() const { return is_hidden_; }
143
144    void set_mount_path(const std::string& mount_path) {
145      mount_path_ = mount_path;
146    }
147
148    void clear_mount_path() { mount_path_.clear(); }
149
150   private:
151    std::string device_path_;
152    std::string mount_path_;
153    std::string system_path_;
154    std::string file_path_;
155    std::string device_label_;
156    std::string drive_label_;
157    std::string vendor_id_;
158    std::string vendor_name_;
159    std::string product_id_;
160    std::string product_name_;
161    std::string fs_uuid_;
162    std::string system_path_prefix_;
163    DeviceType device_type_;
164    uint64 total_size_in_bytes_;
165    bool is_parent_;
166    bool is_read_only_;
167    bool has_media_;
168    bool on_boot_device_;
169    bool on_removable_device_;
170    bool is_hidden_;
171  };
172  typedef std::map<std::string, Disk*> DiskMap;
173
174  // A struct to store information about mount point.
175  struct MountPointInfo {
176    // Device's path.
177    std::string source_path;
178    // Mounted path.
179    std::string mount_path;
180    // Type of mount.
181    MountType mount_type;
182    // Condition of mount.
183    MountCondition mount_condition;
184
185    MountPointInfo(const std::string& source,
186                   const std::string& mount,
187                   const MountType type,
188                   MountCondition condition)
189        : source_path(source),
190          mount_path(mount),
191          mount_type(type),
192          mount_condition(condition) {
193    }
194  };
195
196  // MountPointMap key is mount_path.
197  typedef std::map<std::string, MountPointInfo> MountPointMap;
198
199  // A callback function type which is called after UnmountDeviceRecursively
200  // finishes.
201  typedef base::Callback<void(bool)> UnmountDeviceRecursivelyCallbackType;
202
203  // A callback type for UnmountPath method.
204  typedef base::Callback<void(MountError error_code)> UnmountPathCallback;
205
206  // A callback type for EnsureMountInfoRefreshed method.
207  typedef base::Callback<void(bool success)> EnsureMountInfoRefreshedCallback;
208
209  // Implement this interface to be notified about disk/mount related events.
210  class Observer {
211   public:
212    virtual ~Observer() {}
213
214    // Called when disk mount status is changed.
215    virtual void OnDiskEvent(DiskEvent event, const Disk* disk) = 0;
216    // Called when device status is changed.
217    virtual void OnDeviceEvent(DeviceEvent event,
218                               const std::string& device_path) = 0;
219    // Called after a mount point has been mounted or unmounted.
220    virtual void OnMountEvent(MountEvent event,
221                              MountError error_code,
222                              const MountPointInfo& mount_info) = 0;
223    // Called on format process events.
224    virtual void OnFormatEvent(FormatEvent event,
225                               FormatError error_code,
226                               const std::string& device_path) = 0;
227  };
228
229  virtual ~DiskMountManager() {}
230
231  // Adds an observer.
232  virtual void AddObserver(Observer* observer) = 0;
233
234  // Removes an observer.
235  virtual void RemoveObserver(Observer* observer) = 0;
236
237  // Gets the list of disks found.
238  virtual const DiskMap& disks() const = 0;
239
240  // Returns Disk object corresponding to |source_path| or NULL on failure.
241  virtual const Disk* FindDiskBySourcePath(
242      const std::string& source_path) const = 0;
243
244  // Gets the list of mount points.
245  virtual const MountPointMap& mount_points() const = 0;
246
247  // Refreshes all the information about mounting if it is not yet done and
248  // invokes |callback| when finished. If the information is already refreshed
249  // It just runs |callback| immediately.
250  virtual void EnsureMountInfoRefreshed(
251      const EnsureMountInfoRefreshedCallback& callback) = 0;
252
253  // Mounts a device.
254  // Note that the mount operation may fail. To find out the result, one should
255  // observe DiskMountManager for |Observer::OnMountEvent| event, which will be
256  // raised upon the mount operation completion.
257  virtual void MountPath(const std::string& source_path,
258                         const std::string& source_format,
259                         const std::string& mount_label,
260                         MountType type) = 0;
261
262  // Unmounts a mounted disk.
263  // |UnmountOptions| enum defined in chromeos/dbus/cros_disks_client.h.
264  // When the method is complete, |callback| will be called and observers'
265  // |OnMountEvent| will be raised.
266  //
267  // |callback| may be empty, in which case it gets ignored.
268  virtual void UnmountPath(const std::string& mount_path,
269                           UnmountOptions options,
270                           const UnmountPathCallback& callback) = 0;
271
272  // Formats Device given its mount path. Unmounts the device.
273  // Example: mount_path: /media/VOLUME_LABEL
274  virtual void FormatMountedDevice(const std::string& mount_path) = 0;
275
276  // Unmounts device_path and all of its known children.
277  virtual void UnmountDeviceRecursively(
278      const std::string& device_path,
279      const UnmountDeviceRecursivelyCallbackType& callback) = 0;
280
281  // Used in tests to initialize the manager's disk and mount point sets.
282  // Default implementation does noting. It just fails.
283  virtual bool AddDiskForTest(Disk* disk);
284  virtual bool AddMountPointForTest(const MountPointInfo& mount_point);
285
286  // Returns corresponding string to |type| like "unknown_filesystem".
287  static std::string MountConditionToString(MountCondition type);
288
289  // Returns corresponding string to |type|, like "sd", "usb".
290  static std::string DeviceTypeToString(DeviceType type);
291
292  // Creates the global DiskMountManager instance.
293  static void Initialize();
294
295  // Similar to Initialize(), but can inject an alternative
296  // DiskMountManager such as MockDiskMountManager for testing.
297  // The injected object will be owned by the internal pointer and deleted
298  // by Shutdown().
299  static void InitializeForTesting(DiskMountManager* disk_mount_manager);
300
301  // Destroys the global DiskMountManager instance if it exists.
302  static void Shutdown();
303
304  // Returns a pointer to the global DiskMountManager instance.
305  // Initialize() should already have been called.
306  static DiskMountManager* GetInstance();
307};
308
309}  // namespace disks
310}  // namespace chromeos
311
312#endif  // CHROMEOS_DISKS_DISK_MOUNT_MANAGER_H_
313