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_DBUS_CROS_DISKS_CLIENT_H_
6 #define CHROMEOS_DBUS_CROS_DISKS_CLIENT_H_
7
8 #include <stdint.h>
9
10 #include <memory>
11 #include <string>
12 #include <vector>
13
14 #include "base/callback_forward.h"
15 #include "base/component_export.h"
16 #include "base/macros.h"
17 #include "base/observer_list_types.h"
18 #include "chromeos/dbus/dbus_client.h"
19 #include "chromeos/dbus/dbus_method_call_status.h"
20
21 namespace base {
22 class FilePath;
23 }
24
25 namespace dbus {
26 class Response;
27 }
28
29 // TODO(tbarzic): We should move these enums inside CrosDisksClient,
30 // to be clearer where they come from. Also, most of these are partially or
31 // completely duplicated in third_party/dbus/service_constants.h. We should
32 // probably use enums from service_contstants directly.
33 namespace chromeos {
34
35 // Enum describing types of mount used by cros-disks.
36 enum MountType {
37 MOUNT_TYPE_INVALID,
38 MOUNT_TYPE_DEVICE,
39 MOUNT_TYPE_ARCHIVE,
40 MOUNT_TYPE_NETWORK_STORAGE,
41 };
42
43 // Type of device.
44 enum DeviceType {
45 DEVICE_TYPE_UNKNOWN,
46 DEVICE_TYPE_USB, // USB stick.
47 DEVICE_TYPE_SD, // SD card.
48 DEVICE_TYPE_OPTICAL_DISC, // e.g. Optical disc excluding DVD.
49 DEVICE_TYPE_MOBILE, // Storage on a mobile device (e.g. Android).
50 DEVICE_TYPE_DVD, // DVD.
51 };
52
53 // Mount error code used by cros-disks.
54 // These values are not the same as cros_disks::MountErrorType.
55 // These values are persisted to logs. Entries should not be renumbered and
56 // numeric values should never be reused.
57 enum MountError {
58 MOUNT_ERROR_NONE,
59 MOUNT_ERROR_UNKNOWN,
60 MOUNT_ERROR_INTERNAL,
61 MOUNT_ERROR_INVALID_ARGUMENT,
62 MOUNT_ERROR_INVALID_PATH,
63 MOUNT_ERROR_PATH_ALREADY_MOUNTED,
64 MOUNT_ERROR_PATH_NOT_MOUNTED,
65 MOUNT_ERROR_DIRECTORY_CREATION_FAILED,
66 MOUNT_ERROR_INVALID_MOUNT_OPTIONS,
67 MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS,
68 MOUNT_ERROR_INSUFFICIENT_PERMISSIONS,
69 MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND,
70 MOUNT_ERROR_MOUNT_PROGRAM_FAILED,
71 MOUNT_ERROR_INVALID_DEVICE_PATH,
72 MOUNT_ERROR_UNKNOWN_FILESYSTEM,
73 MOUNT_ERROR_UNSUPPORTED_FILESYSTEM,
74 MOUNT_ERROR_INVALID_ARCHIVE,
75 MOUNT_ERROR_NEED_PASSWORD,
76 MOUNT_ERROR_COUNT,
77 };
78
79 // Rename error reported by cros-disks.
80 enum RenameError {
81 RENAME_ERROR_NONE,
82 RENAME_ERROR_UNKNOWN,
83 RENAME_ERROR_INTERNAL,
84 RENAME_ERROR_INVALID_DEVICE_PATH,
85 RENAME_ERROR_DEVICE_BEING_RENAMED,
86 RENAME_ERROR_UNSUPPORTED_FILESYSTEM,
87 RENAME_ERROR_RENAME_PROGRAM_NOT_FOUND,
88 RENAME_ERROR_RENAME_PROGRAM_FAILED,
89 RENAME_ERROR_DEVICE_NOT_ALLOWED,
90 RENAME_ERROR_LONG_NAME,
91 RENAME_ERROR_INVALID_CHARACTER,
92 };
93
94 // Format error reported by cros-disks.
95 // These values are persisted to logs. Entries should not be renumbered and
96 // numeric values should never be reused.
97 enum FormatError {
98 FORMAT_ERROR_NONE,
99 FORMAT_ERROR_UNKNOWN,
100 FORMAT_ERROR_INTERNAL,
101 FORMAT_ERROR_INVALID_DEVICE_PATH,
102 FORMAT_ERROR_DEVICE_BEING_FORMATTED,
103 FORMAT_ERROR_UNSUPPORTED_FILESYSTEM,
104 FORMAT_ERROR_FORMAT_PROGRAM_NOT_FOUND,
105 FORMAT_ERROR_FORMAT_PROGRAM_FAILED,
106 FORMAT_ERROR_DEVICE_NOT_ALLOWED,
107 FORMAT_ERROR_INVALID_OPTIONS,
108 FORMAT_ERROR_LONG_NAME,
109 FORMAT_ERROR_INVALID_CHARACTER,
110 FORMAT_ERROR_COUNT,
111 };
112
113 // Partition error reported by cros-disks.
114 enum PartitionError {
115 PARTITION_ERROR_NONE = 0,
116 PARTITION_ERROR_UNKNOWN = 1,
117 PARTITION_ERROR_INTERNAL = 2,
118 PARTITION_ERROR_INVALID_DEVICE_PATH = 3,
119 PARTITION_ERROR_DEVICE_BEING_PARTITIONED = 4,
120 PARTITION_ERROR_PROGRAM_NOT_FOUND = 5,
121 PARTITION_ERROR_PROGRAM_FAILED = 6,
122 PARTITION_ERROR_DEVICE_NOT_ALLOWED = 7,
123 };
124
125 // Event type each corresponding to a signal sent from cros-disks.
126 enum MountEventType {
127 CROS_DISKS_DISK_ADDED,
128 CROS_DISKS_DISK_REMOVED,
129 CROS_DISKS_DISK_CHANGED,
130 CROS_DISKS_DEVICE_ADDED,
131 CROS_DISKS_DEVICE_REMOVED,
132 CROS_DISKS_DEVICE_SCANNED,
133 };
134
135 // Mount option to control write permission to a device.
136 enum MountAccessMode {
137 MOUNT_ACCESS_MODE_READ_WRITE,
138 MOUNT_ACCESS_MODE_READ_ONLY,
139 };
140
141 // Whether to mount to a new path or remount a device already mounted.
142 enum RemountOption {
143 // Mount a new device. If the device is already mounted, the mount status is
144 // unchanged and the callback for MountCompleted will receive
145 // MOUNT_ERROR_PATH_ALREADY_MOUNTED error code.
146 REMOUNT_OPTION_MOUNT_NEW_DEVICE,
147 // Remount a device that is already mounted. If the device is not mounted
148 // yet, it will do nothing and the callback for MountCompleted will receive
149 // MOUNT_ERROR_PATH_NOT_MOUNTED error code.
150 REMOUNT_OPTION_REMOUNT_EXISTING_DEVICE,
151 };
152
153 // A class to represent information about a disk sent from cros-disks.
COMPONENT_EXPORT(CHROMEOS_DBUS)154 class COMPONENT_EXPORT(CHROMEOS_DBUS) DiskInfo {
155 public:
156 DiskInfo(const std::string& device_path, dbus::Response* response);
157 ~DiskInfo();
158
159 // Device path. (e.g. /sys/devices/pci0000:00/.../8:0:0:0/block/sdb/sdb1)
160 const std::string& device_path() const { return device_path_; }
161
162 // Disk mount path. (e.g. /media/removable/VOLUME)
163 const std::string& mount_path() const { return mount_path_; }
164
165 // Path of the scsi/mmc/nvme storage device that this disk is a part of.
166 // (e.g. /sys/devices/pci0000:00/.../mmc_host/mmc0/mmc0:0002)
167 const std::string& storage_device_path() const {
168 return storage_device_path_;
169 }
170
171 // Is a drive or not. (i.e. true with /dev/sdb, false with /dev/sdb1)
172 bool is_drive() const { return is_drive_; }
173
174 // Does the disk have media content.
175 bool has_media() const { return has_media_; }
176
177 // Is the disk on device we booted the machine from.
178 bool on_boot_device() const { return on_boot_device_; }
179
180 // Is the disk on a removable device.
181 bool on_removable_device() const { return on_removable_device_; }
182
183 // Is the device read-only.
184 bool is_read_only() const { return is_read_only_; }
185
186 // Returns true if the device should be hidden from the file browser.
187 bool is_hidden() const { return is_hidden_; }
188
189 // Is the disk virtual.
190 bool is_virtual() const { return is_virtual_; }
191
192 // Is the disk auto-mountable.
193 bool is_auto_mountable() const { return is_auto_mountable_; }
194
195 // Disk file path (e.g. /dev/sdb).
196 const std::string& file_path() const { return file_path_; }
197
198 // Disk label.
199 const std::string& label() const { return label_; }
200
201 // Vendor ID of the device (e.g. "18d1").
202 const std::string& vendor_id() const { return vendor_id_; }
203
204 // Vendor name of the device (e.g. "Google Inc.").
205 const std::string& vendor_name() const { return vendor_name_; }
206
207 // Product ID of the device (e.g. "4e11").
208 const std::string& product_id() const { return product_id_; }
209
210 // Product name of the device (e.g. "Nexus One").
211 const std::string& product_name() const { return product_name_; }
212
213 // Disk model. (e.g. "TransMemory")
214 const std::string& drive_label() const { return drive_model_; }
215
216 // Device type. Not working well, yet.
217 DeviceType device_type() const { return device_type_; }
218
219 // Total size of the disk in bytes.
220 uint64_t total_size_in_bytes() const { return total_size_in_bytes_; }
221
222 // Returns file system uuid.
223 const std::string& uuid() const { return uuid_; }
224
225 // Returns file system type identifier.
226 const std::string& file_system_type() const { return file_system_type_; }
227
228 private:
229 void InitializeFromResponse(dbus::Response* response);
230
231 std::string device_path_;
232 std::string mount_path_;
233 std::string storage_device_path_;
234 bool is_drive_;
235 bool has_media_;
236 bool on_boot_device_;
237 bool on_removable_device_;
238 bool is_read_only_;
239 bool is_hidden_;
240 bool is_virtual_;
241 bool is_auto_mountable_;
242
243 std::string file_path_;
244 std::string label_;
245 std::string vendor_id_;
246 std::string vendor_name_;
247 std::string product_id_;
248 std::string product_name_;
249 std::string drive_model_;
250 DeviceType device_type_;
251 uint64_t total_size_in_bytes_;
252 std::string uuid_;
253 std::string file_system_type_;
254 };
255
256 // A struct to represent information about a mount point sent from cros-disks.
COMPONENT_EXPORT(CHROMEOS_DBUS)257 struct COMPONENT_EXPORT(CHROMEOS_DBUS) MountEntry {
258 public:
259 MountEntry()
260 : error_code_(MOUNT_ERROR_UNKNOWN), mount_type_(MOUNT_TYPE_INVALID) {
261 }
262
263 MountEntry(MountError error_code,
264 const std::string& source_path,
265 MountType mount_type,
266 const std::string& mount_path)
267 : error_code_(error_code),
268 source_path_(source_path),
269 mount_type_(mount_type),
270 mount_path_(mount_path) {
271 }
272
273 MountError error_code() const { return error_code_; }
274 const std::string& source_path() const { return source_path_; }
275 MountType mount_type() const { return mount_type_; }
276 const std::string& mount_path() const { return mount_path_; }
277
278 private:
279 MountError error_code_;
280 std::string source_path_;
281 MountType mount_type_;
282 std::string mount_path_;
283 };
284
285 // A class to make the actual DBus calls for cros-disks service.
286 // This class only makes calls, result/error handling should be done
287 // by callbacks.
COMPONENT_EXPORT(CHROMEOS_DBUS)288 class COMPONENT_EXPORT(CHROMEOS_DBUS) CrosDisksClient : public DBusClient {
289 public:
290 // A callback to handle the result of EnumerateDevices.
291 // The argument is the enumerated device paths.
292 typedef base::OnceCallback<void(const std::vector<std::string>& device_paths)>
293 EnumerateDevicesCallback;
294
295 // A callback to handle the result of EnumerateMountEntries.
296 // The argument is the enumerated mount entries.
297 typedef base::OnceCallback<void(const std::vector<MountEntry>& entries)>
298 EnumerateMountEntriesCallback;
299
300 // A callback to handle the result of GetDeviceProperties.
301 // The argument is the information about the specified device.
302 typedef base::OnceCallback<void(const DiskInfo& disk_info)>
303 GetDevicePropertiesCallback;
304
305 // A callback to handle the result of Unmount.
306 // The argument is the unmount error code.
307 typedef base::OnceCallback<void(MountError error_code)> UnmountCallback;
308
309 // A callback to handle the result of SinglePartitionFormat.
310 // The argument is the partition error code.
311 using PartitionCallback = base::OnceCallback<void(PartitionError error_code)>;
312
313 class Observer : public base::CheckedObserver {
314 public:
315 // Called when a mount event signal is received.
316 virtual void OnMountEvent(MountEventType event_type,
317 const std::string& device_path) = 0;
318
319 // Called when a MountCompleted signal is received.
320 virtual void OnMountCompleted(const MountEntry& entry) = 0;
321
322 // Called when a FormatCompleted signal is received.
323 virtual void OnFormatCompleted(FormatError error_code,
324 const std::string& device_path) = 0;
325
326 // Called when a RenameCompleted signal is received.
327 virtual void OnRenameCompleted(RenameError error_code,
328 const std::string& device_path) = 0;
329 };
330
331 ~CrosDisksClient() override;
332
333 // Registers the given |observer| to listen D-Bus signals.
334 virtual void AddObserver(Observer* observer) = 0;
335
336 // Unregisters the |observer| from this instance.
337 virtual void RemoveObserver(Observer* observer) = 0;
338
339 // Calls Mount method. On method call completion, |callback| is called with
340 // |true| on success, or with |false| otherwise.
341 // When mounting an archive, caller may set two optional arguments:
342 // - The |source_format| argument passes the file extension (with the leading
343 // dot, for example ".zip"). If |source_format| is empty then the source
344 // format is auto-detected.
345 // - The |mount_label| argument passes an optional mount label to be used as
346 // the directory name of the mount point. If |mount_label| is empty, the
347 // mount label will be based on the |source_path|.
348 virtual void Mount(const std::string& source_path,
349 const std::string& source_format,
350 const std::string& mount_label,
351 const std::vector<std::string>& mount_options,
352 MountAccessMode access_mode,
353 RemountOption remount,
354 VoidDBusMethodCallback callback) = 0;
355
356 // Calls Unmount method. On method call completion, |callback| is called
357 // with the error code.
358 virtual void Unmount(const std::string& device_path,
359 UnmountCallback callback) = 0;
360
361 // Calls EnumerateDevices method. |callback| is called after the
362 // method call succeeds, otherwise, |error_callback| is called.
363 virtual void EnumerateDevices(EnumerateDevicesCallback callback,
364 base::OnceClosure error_callback) = 0;
365
366 // Calls EnumerateMountEntries. |callback| is called after the
367 // method call succeeds, otherwise, |error_callback| is called.
368 virtual void EnumerateMountEntries(EnumerateMountEntriesCallback callback,
369 base::OnceClosure error_callback) = 0;
370
371 // Calls Format method. On completion, |callback| is called, with |true| on
372 // success, or with |false| otherwise.
373 virtual void Format(const std::string& device_path,
374 const std::string& filesystem,
375 const std::string& label,
376 VoidDBusMethodCallback callback) = 0;
377
378 // Calls SinglePartitionFormat async method. |callback| is called when
379 // response received.
380 virtual void SinglePartitionFormat(const std::string& device_path,
381 PartitionCallback callback) = 0;
382
383 // Calls Rename method. On completion, |callback| is called, with |true| on
384 // success, or with |false| otherwise.
385 virtual void Rename(const std::string& device_path,
386 const std::string& volume_name,
387 VoidDBusMethodCallback callback) = 0;
388
389 // Calls GetDeviceProperties method. |callback| is called after the method
390 // call succeeds, otherwise, |error_callback| is called.
391 virtual void GetDeviceProperties(const std::string& device_path,
392 GetDevicePropertiesCallback callback,
393 base::OnceClosure error_callback) = 0;
394
395 // Factory function, creates a new instance and returns ownership.
396 // For normal usage, access the singleton via DBusThreadManager::Get().
397 static std::unique_ptr<CrosDisksClient> Create();
398
399 // Returns the path of the mount point for archive files.
400 static base::FilePath GetArchiveMountPoint();
401
402 // Returns the path of the mount point for removable disks.
403 static base::FilePath GetRemovableDiskMountPoint();
404
405 // Composes a list of mount options.
406 static std::vector<std::string> ComposeMountOptions(
407 const std::vector<std::string>& options,
408 const std::string& mount_label,
409 MountAccessMode access_mode,
410 RemountOption remount);
411
412 protected:
413 // Create() should be used instead.
414 CrosDisksClient();
415
416 private:
417 DISALLOW_COPY_AND_ASSIGN(CrosDisksClient);
418 };
419
420 } // namespace chromeos
421
422 #endif // CHROMEOS_DBUS_CROS_DISKS_CLIENT_H_
423