blob: 14a7240dc0ee11a889bfb218114b10414e1bdf11 [file] [log] [blame]
[email protected]2321d282012-01-31 23:06:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]4ae73292011-11-15 05:20:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]64e199252012-04-06 01:54:365#include "chromeos/dbus/cros_disks_client.h"
[email protected]4ae73292011-11-15 05:20:186
avi6e1a22d2015-12-21 03:43:207#include <stddef.h>
8#include <stdint.h>
9
[email protected]85b95a2012012-08-07 18:57:2710#include <map>
Hidehiko Abe5a138a22017-10-05 16:22:2111#include <memory>
Hidehiko Abec293cdcf2018-02-08 02:10:4512#include <utility>
[email protected]85b95a2012012-08-07 18:57:2713
[email protected]4ae73292011-11-15 05:20:1814#include "base/bind.h"
[email protected]a5a8b412013-03-04 15:03:1115#include "base/files/file_path.h"
thestigb44bd352014-09-10 01:47:0616#include "base/files/file_util.h"
[email protected]593cf3b2013-03-05 04:16:5217#include "base/location.h"
avi6e1a22d2015-12-21 03:43:2018#include "base/macros.h"
Hidehiko Abe06ce6dc2017-12-08 19:32:0319#include "base/observer_list.h"
[email protected]b307bceb2011-11-17 07:49:5520#include "base/stl_util.h"
[email protected]afa339d72013-06-11 06:32:5121#include "base/strings/stringprintf.h"
[email protected]49c4cf852013-09-27 19:28:2422#include "base/sys_info.h"
[email protected]593cf3b2013-03-05 04:16:5223#include "base/task_runner_util.h"
[email protected]81836aed2013-07-09 23:41:1224#include "base/values.h"
satorux8fd293802014-10-30 08:23:1225#include "chromeos/dbus/fake_cros_disks_client.h"
[email protected]4ae73292011-11-15 05:20:1826#include "dbus/bus.h"
27#include "dbus/message.h"
[email protected]216ed0b2012-02-14 21:29:0628#include "dbus/object_path.h"
[email protected]4ae73292011-11-15 05:20:1829#include "dbus/object_proxy.h"
[email protected]81836aed2013-07-09 23:41:1230#include "dbus/values_util.h"
[email protected]4ae73292011-11-15 05:20:1831#include "third_party/cros_system_api/dbus/service_constants.h"
32
33namespace chromeos {
34
35namespace {
36
Sergei Datsenko1fadef32018-05-14 02:14:2337constexpr char kReadOnlyOption[] = "ro";
38constexpr char kReadWriteOption[] = "rw";
39constexpr char kRemountOption[] = "remount";
40constexpr char kMountLabelOption[] = "mountlabel";
41constexpr char kLazyUnmountOption[] = "lazy";
[email protected]10795ae2012-10-10 07:33:4942
[email protected]2321d282012-01-31 23:06:5943// Checks if retrieved media type is in boundaries of DeviceMediaType.
avi6e1a22d2015-12-21 03:43:2044bool IsValidMediaType(uint32_t type) {
45 return type < static_cast<uint32_t>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
[email protected]2321d282012-01-31 23:06:5946}
47
[email protected]2321d282012-01-31 23:06:5948// Translates enum used in cros-disks to enum used in Chrome.
49// Note that we could just do static_cast, but this is less sensitive to
50// changes in cros-disks.
avi6e1a22d2015-12-21 03:43:2051DeviceType DeviceMediaTypeToDeviceType(uint32_t media_type_uint32) {
[email protected]2321d282012-01-31 23:06:5952 if (!IsValidMediaType(media_type_uint32))
53 return DEVICE_TYPE_UNKNOWN;
54
55 cros_disks::DeviceMediaType media_type =
56 cros_disks::DeviceMediaType(media_type_uint32);
57
58 switch (media_type) {
59 case(cros_disks::DEVICE_MEDIA_UNKNOWN):
60 return DEVICE_TYPE_UNKNOWN;
61 case(cros_disks::DEVICE_MEDIA_USB):
62 return DEVICE_TYPE_USB;
63 case(cros_disks::DEVICE_MEDIA_SD):
64 return DEVICE_TYPE_SD;
65 case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
66 return DEVICE_TYPE_OPTICAL_DISC;
67 case(cros_disks::DEVICE_MEDIA_MOBILE):
68 return DEVICE_TYPE_MOBILE;
[email protected]f4ae40ac2012-05-04 21:57:0069 case(cros_disks::DEVICE_MEDIA_DVD):
70 return DEVICE_TYPE_DVD;
[email protected]2321d282012-01-31 23:06:5971 default:
72 return DEVICE_TYPE_UNKNOWN;
73 }
[email protected]4ae73292011-11-15 05:20:1874}
75
Anand K. Mistry25b15982018-08-16 01:19:1376MountError CrosDisksMountErrorToChromeMountError(
77 cros_disks::MountErrorType mount_error) {
78 switch (mount_error) {
79 case cros_disks::MOUNT_ERROR_NONE:
80 return MOUNT_ERROR_NONE;
81 case cros_disks::MOUNT_ERROR_UNKNOWN:
82 return MOUNT_ERROR_UNKNOWN;
83 case cros_disks::MOUNT_ERROR_INTERNAL:
84 return MOUNT_ERROR_INTERNAL;
85 case cros_disks::MOUNT_ERROR_INVALID_ARGUMENT:
86 return MOUNT_ERROR_INVALID_ARGUMENT;
87 case cros_disks::MOUNT_ERROR_INVALID_PATH:
88 return MOUNT_ERROR_INVALID_PATH;
89 case cros_disks::MOUNT_ERROR_PATH_ALREADY_MOUNTED:
90 return MOUNT_ERROR_PATH_ALREADY_MOUNTED;
91 case cros_disks::MOUNT_ERROR_PATH_NOT_MOUNTED:
92 return MOUNT_ERROR_PATH_NOT_MOUNTED;
93 case cros_disks::MOUNT_ERROR_DIRECTORY_CREATION_FAILED:
94 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
95 case cros_disks::MOUNT_ERROR_INVALID_MOUNT_OPTIONS:
96 return MOUNT_ERROR_INVALID_MOUNT_OPTIONS;
97 case cros_disks::MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS:
98 return MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS;
99 case cros_disks::MOUNT_ERROR_INSUFFICIENT_PERMISSIONS:
100 return MOUNT_ERROR_INSUFFICIENT_PERMISSIONS;
101 case cros_disks::MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND:
102 return MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND;
103 case cros_disks::MOUNT_ERROR_MOUNT_PROGRAM_FAILED:
104 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
105 case cros_disks::MOUNT_ERROR_INVALID_DEVICE_PATH:
106 return MOUNT_ERROR_INVALID_DEVICE_PATH;
107 case cros_disks::MOUNT_ERROR_UNKNOWN_FILESYSTEM:
108 return MOUNT_ERROR_UNKNOWN_FILESYSTEM;
109 case cros_disks::MOUNT_ERROR_UNSUPPORTED_FILESYSTEM:
110 return MOUNT_ERROR_UNSUPPORTED_FILESYSTEM;
111 case cros_disks::MOUNT_ERROR_INVALID_ARCHIVE:
112 return MOUNT_ERROR_INVALID_ARCHIVE;
113 case cros_disks::MOUNT_ERROR_UNSUPPORTED_ARCHIVE:
114 // TODO(amistry): Add MOUNT_ERROR_UNSUPPORTED_ARCHIVE.
115 return MOUNT_ERROR_UNKNOWN;
116 default:
117 NOTREACHED() << "Unrecognised mount error code " << mount_error;
118 return MOUNT_ERROR_UNKNOWN;
119 }
120}
121
[email protected]d7760592014-05-16 07:57:52122bool ReadMountEntryFromDbus(dbus::MessageReader* reader, MountEntry* entry) {
avi6e1a22d2015-12-21 03:43:20123 uint32_t error_code = 0;
[email protected]d7760592014-05-16 07:57:52124 std::string source_path;
avi6e1a22d2015-12-21 03:43:20125 uint32_t mount_type = 0;
[email protected]d7760592014-05-16 07:57:52126 std::string mount_path;
127 if (!reader->PopUint32(&error_code) ||
128 !reader->PopString(&source_path) ||
129 !reader->PopUint32(&mount_type) ||
130 !reader->PopString(&mount_path)) {
131 return false;
132 }
Anand K. Mistry25b15982018-08-16 01:19:13133 *entry =
134 MountEntry(CrosDisksMountErrorToChromeMountError(
135 static_cast<cros_disks::MountErrorType>(error_code)),
136 source_path, static_cast<MountType>(mount_type), mount_path);
[email protected]d7760592014-05-16 07:57:52137 return true;
138}
139
[email protected]4ae73292011-11-15 05:20:18140// The CrosDisksClient implementation.
141class CrosDisksClientImpl : public CrosDisksClient {
142 public:
Hidehiko Abe06ce6dc2017-12-08 19:32:03143 CrosDisksClientImpl() : proxy_(nullptr), weak_ptr_factory_(this) {}
144
145 // CrosDisksClient override.
146 void AddObserver(Observer* observer) override {
147 observer_list_.AddObserver(observer);
148 }
149
150 // CrosDisksClient override.
151 void RemoveObserver(Observer* observer) override {
152 observer_list_.RemoveObserver(observer);
153 }
[email protected]4ae73292011-11-15 05:20:18154
155 // CrosDisksClient override.
dcheng0280cb62015-01-16 07:37:50156 void Mount(const std::string& source_path,
157 const std::string& source_format,
158 const std::string& mount_label,
Sergei Datsenkod19248182018-05-11 01:52:56159 const std::vector<std::string>& mount_options,
yamaguchi585d5402016-08-02 09:27:36160 MountAccessMode access_mode,
yamaguchifa8efc72016-10-21 15:05:51161 RemountOption remount,
Hidehiko Abec293cdcf2018-02-08 02:10:45162 VoidDBusMethodCallback callback) override {
[email protected]4ae73292011-11-15 05:20:18163 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
164 cros_disks::kMount);
165 dbus::MessageWriter writer(&method_call);
166 writer.AppendString(source_path);
[email protected]b9f22d12012-04-25 21:46:48167 writer.AppendString(source_format);
Sergei Datsenkod19248182018-05-11 01:52:56168 std::vector<std::string> options =
169 ComposeMountOptions(mount_options, mount_label, access_mode, remount);
170 writer.AppendArrayOfStrings(options);
Hidehiko Abec293cdcf2018-02-08 02:10:45171 proxy_->CallMethod(
172 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
173 base::BindOnce(&CrosDisksClientImpl::OnVoidMethod,
174 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
[email protected]4ae73292011-11-15 05:20:18175 }
176
177 // CrosDisksClient override.
dcheng0280cb62015-01-16 07:37:50178 void Unmount(const std::string& device_path,
179 UnmountOptions options,
Hidehiko Abec293cdcf2018-02-08 02:10:45180 VoidDBusMethodCallback callback) override {
[email protected]4ae73292011-11-15 05:20:18181 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
182 cros_disks::kUnmount);
183 dbus::MessageWriter writer(&method_call);
184 writer.AppendString(device_path);
[email protected]10795ae2012-10-10 07:33:49185
benchan8bcaea12017-03-11 00:26:50186 std::vector<std::string> unmount_options;
[email protected]10795ae2012-10-10 07:33:49187 if (options == UNMOUNT_OPTIONS_LAZY)
188 unmount_options.push_back(kLazyUnmountOption);
189
[email protected]4ae73292011-11-15 05:20:18190 writer.AppendArrayOfStrings(unmount_options);
Hidehiko Abec293cdcf2018-02-08 02:10:45191 proxy_->CallMethod(
192 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
193 base::BindOnce(&CrosDisksClientImpl::OnUnmount,
194 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
[email protected]4ae73292011-11-15 05:20:18195 }
196
Aga Wronskaddc1a752017-12-01 19:44:02197 void EnumerateDevices(const EnumerateDevicesCallback& callback,
198 const base::Closure& error_callback) override {
199 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
200 cros_disks::kEnumerateDevices);
201 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
202 base::BindOnce(&CrosDisksClientImpl::OnEnumerateDevices,
203 weak_ptr_factory_.GetWeakPtr(), callback,
204 error_callback));
[email protected]4ae73292011-11-15 05:20:18205 }
206
207 // CrosDisksClient override.
dcheng0280cb62015-01-16 07:37:50208 void EnumerateMountEntries(const EnumerateMountEntriesCallback& callback,
209 const base::Closure& error_callback) override {
[email protected]d7760592014-05-16 07:57:52210 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
211 cros_disks::kEnumerateMountEntries);
212 proxy_->CallMethod(
213 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
Hidehiko Abed62ed3e2017-09-05 05:16:56214 base::BindOnce(&CrosDisksClientImpl::OnEnumerateMountEntries,
215 weak_ptr_factory_.GetWeakPtr(), callback,
216 error_callback));
[email protected]d7760592014-05-16 07:57:52217 }
218
219 // CrosDisksClient override.
dcheng0280cb62015-01-16 07:37:50220 void Format(const std::string& device_path,
221 const std::string& filesystem,
Hidehiko Abec293cdcf2018-02-08 02:10:45222 VoidDBusMethodCallback callback) override {
[email protected]4ae73292011-11-15 05:20:18223 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
[email protected]f026c0f2014-05-06 21:52:35224 cros_disks::kFormat);
[email protected]4ae73292011-11-15 05:20:18225 dbus::MessageWriter writer(&method_call);
226 writer.AppendString(device_path);
227 writer.AppendString(filesystem);
[email protected]f026c0f2014-05-06 21:52:35228 // No format option is currently specified, but we can later use this
229 // argument to specify options for the format operation.
230 std::vector<std::string> format_options;
231 writer.AppendArrayOfStrings(format_options);
Hidehiko Abec293cdcf2018-02-08 02:10:45232 proxy_->CallMethod(
233 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
234 base::BindOnce(&CrosDisksClientImpl::OnVoidMethod,
235 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
[email protected]4ae73292011-11-15 05:20:18236 }
237
Klemen Kozjekbf5610f2017-08-25 20:20:09238 void Rename(const std::string& device_path,
239 const std::string& volume_name,
Hidehiko Abec293cdcf2018-02-08 02:10:45240 VoidDBusMethodCallback callback) override {
Klemen Kozjekbf5610f2017-08-25 20:20:09241 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
242 cros_disks::kRename);
243 dbus::MessageWriter writer(&method_call);
244 writer.AppendString(device_path);
245 writer.AppendString(volume_name);
Hidehiko Abec293cdcf2018-02-08 02:10:45246 proxy_->CallMethod(
247 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
248 base::BindOnce(&CrosDisksClientImpl::OnVoidMethod,
249 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
Klemen Kozjekbf5610f2017-08-25 20:20:09250 }
251
[email protected]4ae73292011-11-15 05:20:18252 // CrosDisksClient override.
dcheng0280cb62015-01-16 07:37:50253 void GetDeviceProperties(const std::string& device_path,
254 const GetDevicePropertiesCallback& callback,
255 const base::Closure& error_callback) override {
[email protected]4ae73292011-11-15 05:20:18256 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
257 cros_disks::kGetDeviceProperties);
258 dbus::MessageWriter writer(&method_call);
259 writer.AppendString(device_path);
Hidehiko Abed62ed3e2017-09-05 05:16:56260 proxy_->CallMethod(
261 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
262 base::BindOnce(&CrosDisksClientImpl::OnGetDeviceProperties,
263 weak_ptr_factory_.GetWeakPtr(), device_path, callback,
264 error_callback));
[email protected]4ae73292011-11-15 05:20:18265 }
266
[email protected]c5fd5362013-08-27 12:23:04267 protected:
dcheng0280cb62015-01-16 07:37:50268 void Init(dbus::Bus* bus) override {
[email protected]c5fd5362013-08-27 12:23:04269 proxy_ = bus->GetObjectProxy(
270 cros_disks::kCrosDisksServiceName,
271 dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
Hidehiko Abe06ce6dc2017-12-08 19:32:03272
273 // Register handlers for D-Bus signals.
274 constexpr SignalEventTuple kSignalEventTuples[] = {
275 {cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED},
276 {cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED},
277 {cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED},
278 {cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED},
279 {cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED},
280 {cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED},
281 };
282 for (const auto& entry : kSignalEventTuples) {
283 proxy_->ConnectToSignal(
284 cros_disks::kCrosDisksInterface, entry.signal_name,
285 base::BindRepeating(&CrosDisksClientImpl::OnMountEvent,
286 weak_ptr_factory_.GetWeakPtr(), entry.event_type),
287 base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
288 weak_ptr_factory_.GetWeakPtr()));
289 }
290
291 proxy_->ConnectToSignal(
292 cros_disks::kCrosDisksInterface, cros_disks::kMountCompleted,
293 base::BindRepeating(&CrosDisksClientImpl::OnMountCompleted,
294 weak_ptr_factory_.GetWeakPtr()),
295 base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
296 weak_ptr_factory_.GetWeakPtr()));
297
298 proxy_->ConnectToSignal(
299 cros_disks::kCrosDisksInterface, cros_disks::kFormatCompleted,
300 base::BindRepeating(&CrosDisksClientImpl::OnFormatCompleted,
301 weak_ptr_factory_.GetWeakPtr()),
302 base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
303 weak_ptr_factory_.GetWeakPtr()));
304
305 proxy_->ConnectToSignal(
306 cros_disks::kCrosDisksInterface, cros_disks::kRenameCompleted,
307 base::BindRepeating(&CrosDisksClientImpl::OnRenameCompleted,
308 weak_ptr_factory_.GetWeakPtr()),
309 base::BindOnce(&CrosDisksClientImpl::OnSignalConnected,
310 weak_ptr_factory_.GetWeakPtr()));
[email protected]c5fd5362013-08-27 12:23:04311 }
312
[email protected]4ae73292011-11-15 05:20:18313 private:
314 // A struct to contain a pair of signal name and mount event type.
[email protected]a0278d52014-05-06 03:36:15315 // Used by SetMountEventHandler.
[email protected]4ae73292011-11-15 05:20:18316 struct SignalEventTuple {
317 const char *signal_name;
318 MountEventType event_type;
319 };
320
Hidehiko Abec293cdcf2018-02-08 02:10:45321 // Handles the result of D-Bus method call with no return value.
322 void OnVoidMethod(VoidDBusMethodCallback callback, dbus::Response* response) {
323 std::move(callback).Run(response);
[email protected]4ae73292011-11-15 05:20:18324 }
325
[email protected]d7760592014-05-16 07:57:52326 // Handles the result of Unmount and calls |callback| or |error_callback|.
Hidehiko Abec293cdcf2018-02-08 02:10:45327 void OnUnmount(VoidDBusMethodCallback callback, dbus::Response* response) {
[email protected]4ae73292011-11-15 05:20:18328 if (!response) {
Hidehiko Abec293cdcf2018-02-08 02:10:45329 std::move(callback).Run(false);
[email protected]4ae73292011-11-15 05:20:18330 return;
331 }
[email protected]ddcb18e2013-09-19 07:17:28332
333 // Temporarly allow Unmount method to report failure both by setting dbus
334 // error (in which case response is not set) and by returning mount error
335 // different from MOUNT_ERROR_NONE. This is done so we can change Unmount
336 // method to return mount error (http://crbug.com/288974) without breaking
337 // Chrome.
338 // TODO(tbarzic): When Unmount implementation is changed on cros disks side,
339 // make this fail if reader is not able to read the error code value from
340 // the response.
341 dbus::MessageReader reader(response);
avi6e1a22d2015-12-21 03:43:20342 uint32_t error_code = 0;
[email protected]ddcb18e2013-09-19 07:17:28343 if (reader.PopUint32(&error_code) &&
Anand K. Mistry25b15982018-08-16 01:19:13344 CrosDisksMountErrorToChromeMountError(
345 static_cast<cros_disks::MountErrorType>(error_code)) !=
346 MOUNT_ERROR_NONE) {
Hidehiko Abec293cdcf2018-02-08 02:10:45347 std::move(callback).Run(false);
[email protected]ddcb18e2013-09-19 07:17:28348 return;
349 }
350
Hidehiko Abec293cdcf2018-02-08 02:10:45351 std::move(callback).Run(true);
[email protected]4ae73292011-11-15 05:20:18352 }
353
Aga Wronskaddc1a752017-12-01 19:44:02354 // Handles the result of EnumerateDevices and EnumarateAutoMountableDevices.
355 // Calls |callback| or |error_callback|.
356 void OnEnumerateDevices(const EnumerateDevicesCallback& callback,
357 const base::Closure& error_callback,
358 dbus::Response* response) {
[email protected]4ae73292011-11-15 05:20:18359 if (!response) {
360 error_callback.Run();
361 return;
362 }
363 dbus::MessageReader reader(response);
364 std::vector<std::string> device_paths;
365 if (!reader.PopArrayOfStrings(&device_paths)) {
366 LOG(ERROR) << "Invalid response: " << response->ToString();
367 error_callback.Run();
368 return;
369 }
370 callback.Run(device_paths);
371 }
372
[email protected]d7760592014-05-16 07:57:52373 // Handles the result of EnumerateMountEntries and calls |callback| or
374 // |error_callback|.
375 void OnEnumerateMountEntries(
376 const EnumerateMountEntriesCallback& callback,
377 const base::Closure& error_callback,
378 dbus::Response* response) {
379 if (!response) {
380 error_callback.Run();
381 return;
382 }
383
384 dbus::MessageReader reader(response);
385 dbus::MessageReader array_reader(NULL);
386 if (!reader.PopArray(&array_reader)) {
387 LOG(ERROR) << "Invalid response: " << response->ToString();
388 error_callback.Run();
389 return;
390 }
391
392 std::vector<MountEntry> entries;
393 while (array_reader.HasMoreData()) {
394 MountEntry entry;
395 dbus::MessageReader sub_reader(NULL);
396 if (!array_reader.PopStruct(&sub_reader) ||
397 !ReadMountEntryFromDbus(&sub_reader, &entry)) {
398 LOG(ERROR) << "Invalid response: " << response->ToString();
399 error_callback.Run();
400 return;
401 }
402 entries.push_back(entry);
403 }
404 callback.Run(entries);
405 }
406
[email protected]4ae73292011-11-15 05:20:18407 // Handles the result of GetDeviceProperties and calls |callback| or
408 // |error_callback|.
409 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35410 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53411 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18412 dbus::Response* response) {
413 if (!response) {
414 error_callback.Run();
415 return;
416 }
417 DiskInfo disk(device_path, response);
418 callback.Run(disk);
419 }
420
Hidehiko Abe06ce6dc2017-12-08 19:32:03421 // Handles mount event signals and notifies observers.
422 void OnMountEvent(MountEventType event_type, dbus::Signal* signal) {
[email protected]4ae73292011-11-15 05:20:18423 dbus::MessageReader reader(signal);
424 std::string device;
425 if (!reader.PopString(&device)) {
426 LOG(ERROR) << "Invalid signal: " << signal->ToString();
427 return;
428 }
Hidehiko Abe06ce6dc2017-12-08 19:32:03429
430 for (auto& observer : observer_list_)
431 observer.OnMountEvent(event_type, device);
[email protected]4ae73292011-11-15 05:20:18432 }
433
Hidehiko Abe06ce6dc2017-12-08 19:32:03434 // Handles MountCompleted signal and notifies observers.
435 void OnMountCompleted(dbus::Signal* signal) {
[email protected]4ae73292011-11-15 05:20:18436 dbus::MessageReader reader(signal);
[email protected]d7760592014-05-16 07:57:52437 MountEntry entry;
438 if (!ReadMountEntryFromDbus(&reader, &entry)) {
[email protected]4ae73292011-11-15 05:20:18439 LOG(ERROR) << "Invalid signal: " << signal->ToString();
440 return;
441 }
Hidehiko Abe06ce6dc2017-12-08 19:32:03442
443 for (auto& observer : observer_list_)
444 observer.OnMountCompleted(entry);
[email protected]4ae73292011-11-15 05:20:18445 }
446
Hidehiko Abe06ce6dc2017-12-08 19:32:03447 // Handles FormatCompleted signal and notifies observers.
448 void OnFormatCompleted(dbus::Signal* signal) {
[email protected]a0278d52014-05-06 03:36:15449 dbus::MessageReader reader(signal);
avi6e1a22d2015-12-21 03:43:20450 uint32_t error_code = 0;
[email protected]a0278d52014-05-06 03:36:15451 std::string device_path;
452 if (!reader.PopUint32(&error_code) || !reader.PopString(&device_path)) {
453 LOG(ERROR) << "Invalid signal: " << signal->ToString();
454 return;
455 }
Hidehiko Abe06ce6dc2017-12-08 19:32:03456
457 for (auto& observer : observer_list_) {
458 observer.OnFormatCompleted(static_cast<FormatError>(error_code),
459 device_path);
460 }
[email protected]a0278d52014-05-06 03:36:15461 }
462
Hidehiko Abe06ce6dc2017-12-08 19:32:03463 // Handles RenameCompleted signal and notifies observers.
464 void OnRenameCompleted(dbus::Signal* signal) {
Klemen Kozjekbf5610f2017-08-25 20:20:09465 dbus::MessageReader reader(signal);
466 uint32_t error_code = 0;
467 std::string device_path;
468 if (!reader.PopUint32(&error_code) || !reader.PopString(&device_path)) {
469 LOG(ERROR) << "Invalid signal: " << signal->ToString();
470 return;
471 }
Hidehiko Abe06ce6dc2017-12-08 19:32:03472
473 for (auto& observer : observer_list_) {
474 observer.OnRenameCompleted(static_cast<RenameError>(error_code),
475 device_path);
476 }
Klemen Kozjekbf5610f2017-08-25 20:20:09477 }
478
[email protected]4ae73292011-11-15 05:20:18479 // Handles the result of signal connection setup.
480 void OnSignalConnected(const std::string& interface,
481 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43482 bool succeeded) {
483 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18484 signal << " failed.";
485 }
486
487 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16488
Trent Apteda250ec3ab2018-08-19 08:52:19489 base::ObserverList<Observer>::Unchecked observer_list_;
Hidehiko Abe06ce6dc2017-12-08 19:32:03490
[email protected]926957b2012-09-07 05:34:16491 // Note: This should remain the last member so it'll be destroyed and
492 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18493 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
494
495 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
496};
497
[email protected]85b95a2012012-08-07 18:57:27498} // namespace
[email protected]4ae73292011-11-15 05:20:18499
500////////////////////////////////////////////////////////////////////////////////
501// DiskInfo
502
503DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
504 : device_path_(device_path),
505 is_drive_(false),
506 has_media_(false),
507 on_boot_device_(false),
[email protected]79ed457b2014-07-22 04:07:26508 on_removable_device_(false),
[email protected]4ae73292011-11-15 05:20:18509 is_read_only_(false),
Aga Wronskaddc1a752017-12-01 19:44:02510 is_hidden_(true),
511 is_virtual_(false),
Anand K. Mistry2a5ed862018-08-08 00:53:31512 is_auto_mountable_(false),
Aga Wronskaddc1a752017-12-01 19:44:02513 device_type_(DEVICE_TYPE_UNKNOWN),
514 total_size_in_bytes_(0) {
[email protected]4ae73292011-11-15 05:20:18515 InitializeFromResponse(response);
516}
517
Chris Watkins2c529d62017-11-29 02:14:41518DiskInfo::~DiskInfo() = default;
[email protected]4ae73292011-11-15 05:20:18519
[email protected]85b95a2012012-08-07 18:57:27520// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18521// Below is an example of |response|'s raw message (long string is ellipsized).
522//
523//
524// message_type: MESSAGE_METHOD_RETURN
525// destination: :1.8
526// sender: :1.16
527// signature: a{sv}
528// serial: 96
529// reply_serial: 267
530//
531// array [
532// dict entry {
533// string "DeviceFile"
534// variant string "/dev/sdb"
535// }
536// dict entry {
537// string "DeviceIsDrive"
538// variant bool true
539// }
540// dict entry {
541// string "DeviceIsMediaAvailable"
542// variant bool true
543// }
544// dict entry {
545// string "DeviceIsMounted"
546// variant bool false
547// }
548// dict entry {
549// string "DeviceIsOnBootDevice"
550// variant bool false
551// }
552// dict entry {
[email protected]79ed457b2014-07-22 04:07:26553// string "DeviceIsOnRemovableDevice"
554// variant bool true
555// }
556// dict entry {
[email protected]4ae73292011-11-15 05:20:18557// string "DeviceIsReadOnly"
558// variant bool false
559// }
560// dict entry {
561// string "DeviceIsVirtual"
562// variant bool false
563// }
564// dict entry {
565// string "DeviceMediaType"
avi6e1a22d2015-12-21 03:43:20566// variant uint32_t 1
[email protected]4ae73292011-11-15 05:20:18567// }
568// dict entry {
569// string "DeviceMountPaths"
570// variant array [
571// ]
572// }
573// dict entry {
574// string "DevicePresentationHide"
575// variant bool true
576// }
577// dict entry {
578// string "DeviceSize"
avi6e1a22d2015-12-21 03:43:20579// variant uint64_t 7998537728
[email protected]4ae73292011-11-15 05:20:18580// }
581// dict entry {
582// string "DriveIsRotational"
583// variant bool false
584// }
585// dict entry {
[email protected]202e9fee2012-09-13 20:21:29586// string "VendorId"
587// variant string "18d1"
588// }
589// dict entry {
590// string "VendorName"
591// variant string "Google Inc."
592// }
593// dict entry {
594// string "ProductId"
595// variant string "4e11"
596// }
597// dict entry {
598// string "ProductName"
599// variant string "Nexus One"
600// }
601// dict entry {
[email protected]4ae73292011-11-15 05:20:18602// string "DriveModel"
603// variant string "TransMemory"
604// }
605// dict entry {
606// string "IdLabel"
607// variant string ""
608// }
609// dict entry {
610// string "IdUuid"
611// variant string ""
612// }
613// dict entry {
614// string "NativePath"
615// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
616// }
Klemen Kozjek46f1c6192017-08-25 19:20:54617// dict entry {
618// string "FileSystemType"
619// variant string "vfat"
620// }
[email protected]4ae73292011-11-15 05:20:18621// ]
622void DiskInfo::InitializeFromResponse(dbus::Response* response) {
[email protected]81836aed2013-07-09 23:41:12623 dbus::MessageReader reader(response);
dcheng0a6e80c2016-04-08 18:37:38624 std::unique_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
[email protected]81836aed2013-07-09 23:41:12625 base::DictionaryValue* properties = NULL;
626 if (!value || !value->GetAsDictionary(&properties))
[email protected]4ae73292011-11-15 05:20:18627 return;
[email protected]4ae73292011-11-15 05:20:18628
[email protected]81836aed2013-07-09 23:41:12629 properties->GetBooleanWithoutPathExpansion(
630 cros_disks::kDeviceIsDrive, &is_drive_);
631 properties->GetBooleanWithoutPathExpansion(
632 cros_disks::kDeviceIsReadOnly, &is_read_only_);
633 properties->GetBooleanWithoutPathExpansion(
634 cros_disks::kDevicePresentationHide, &is_hidden_);
635 properties->GetBooleanWithoutPathExpansion(
636 cros_disks::kDeviceIsMediaAvailable, &has_media_);
637 properties->GetBooleanWithoutPathExpansion(
638 cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
[email protected]79ed457b2014-07-22 04:07:26639 properties->GetBooleanWithoutPathExpansion(
640 cros_disks::kDeviceIsOnRemovableDevice, &on_removable_device_);
Aga Wronskaddc1a752017-12-01 19:44:02641 properties->GetBooleanWithoutPathExpansion(cros_disks::kDeviceIsVirtual,
642 &is_virtual_);
Anand K. Mistry2a5ed862018-08-08 00:53:31643 properties->GetBooleanWithoutPathExpansion(cros_disks::kIsAutoMountable,
644 &is_auto_mountable_);
[email protected]81836aed2013-07-09 23:41:12645 properties->GetStringWithoutPathExpansion(
646 cros_disks::kNativePath, &system_path_);
647 properties->GetStringWithoutPathExpansion(
648 cros_disks::kDeviceFile, &file_path_);
649 properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
650 properties->GetStringWithoutPathExpansion(
651 cros_disks::kVendorName, &vendor_name_);
652 properties->GetStringWithoutPathExpansion(
653 cros_disks::kProductId, &product_id_);
654 properties->GetStringWithoutPathExpansion(
655 cros_disks::kProductName, &product_name_);
656 properties->GetStringWithoutPathExpansion(
657 cros_disks::kDriveModel, &drive_model_);
658 properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
659 properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
Klemen Kozjek46f1c6192017-08-25 19:20:54660 properties->GetStringWithoutPathExpansion(cros_disks::kFileSystemType,
661 &file_system_type_);
[email protected]2321d282012-01-31 23:06:59662
avi6e1a22d2015-12-21 03:43:20663 // dbus::PopDataAsValue() pops uint64_t as double.
664 // The top 11 bits of uint64_t are dropped by the use of double. But, this
665 // works
[email protected]81836aed2013-07-09 23:41:12666 // unless the size exceeds 8 PB.
667 double device_size_double = 0;
668 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
669 &device_size_double))
670 total_size_in_bytes_ = device_size_double;
671
avi6e1a22d2015-12-21 03:43:20672 // dbus::PopDataAsValue() pops uint32_t as double.
[email protected]81836aed2013-07-09 23:41:12673 double media_type_double = 0;
674 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
675 &media_type_double))
676 device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
677
678 base::ListValue* mount_paths = NULL;
679 if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
680 &mount_paths))
681 mount_paths->GetString(0, &mount_path_);
[email protected]4ae73292011-11-15 05:20:18682}
683
684////////////////////////////////////////////////////////////////////////////////
685// CrosDisksClient
686
Chris Watkins2c529d62017-11-29 02:14:41687CrosDisksClient::CrosDisksClient() = default;
[email protected]4ae73292011-11-15 05:20:18688
Chris Watkins2c529d62017-11-29 02:14:41689CrosDisksClient::~CrosDisksClient() = default;
[email protected]4ae73292011-11-15 05:20:18690
691// static
[email protected]c5fd5362013-08-27 12:23:04692CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
[email protected]e8db03d62012-03-31 04:08:38693 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]c5fd5362013-08-27 12:23:04694 return new CrosDisksClientImpl();
jamescook2b590992016-09-14 15:28:45695 DCHECK_EQ(FAKE_DBUS_CLIENT_IMPLEMENTATION, type);
satorux8fd293802014-10-30 08:23:12696 return new FakeCrosDisksClient();
[email protected]4ae73292011-11-15 05:20:18697}
698
[email protected]a5a8b412013-03-04 15:03:11699// static
700base::FilePath CrosDisksClient::GetArchiveMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24701 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11702 FILE_PATH_LITERAL("/media/archive") :
703 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
704}
705
706// static
707base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24708 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11709 FILE_PATH_LITERAL("/media/removable") :
710 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
711}
712
yamaguchi585d5402016-08-02 09:27:36713// static
714std::vector<std::string> CrosDisksClient::ComposeMountOptions(
Sergei Datsenkod19248182018-05-11 01:52:56715 const std::vector<std::string>& options,
yamaguchi585d5402016-08-02 09:27:36716 const std::string& mount_label,
yamaguchifa8efc72016-10-21 15:05:51717 MountAccessMode access_mode,
718 RemountOption remount) {
Sergei Datsenkod19248182018-05-11 01:52:56719 std::vector<std::string> mount_options = options;
yamaguchi585d5402016-08-02 09:27:36720 switch (access_mode) {
721 case MOUNT_ACCESS_MODE_READ_ONLY:
722 mount_options.push_back(kReadOnlyOption);
723 break;
724 case MOUNT_ACCESS_MODE_READ_WRITE:
725 mount_options.push_back(kReadWriteOption);
726 break;
727 }
yamaguchifa8efc72016-10-21 15:05:51728 if (remount == REMOUNT_OPTION_REMOUNT_EXISTING_DEVICE) {
729 mount_options.push_back(kRemountOption);
730 }
yamaguchi585d5402016-08-02 09:27:36731
732 if (!mount_label.empty()) {
733 std::string mount_label_option =
734 base::StringPrintf("%s=%s", kMountLabelOption, mount_label.c_str());
735 mount_options.push_back(mount_label_option);
736 }
Sergei Datsenkod19248182018-05-11 01:52:56737
yamaguchi585d5402016-08-02 09:27:36738 return mount_options;
739}
740
[email protected]4ae73292011-11-15 05:20:18741} // namespace chromeos