blob: 1baa32d6399a8d6f44411b594701abf7a139ab8c [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
[email protected]85b95a2012012-08-07 18:57:277#include <map>
8
[email protected]4ae73292011-11-15 05:20:189#include "base/bind.h"
[email protected]593cf3b2013-03-05 04:16:5210#include "base/file_util.h"
[email protected]a5a8b412013-03-04 15:03:1111#include "base/files/file_path.h"
[email protected]593cf3b2013-03-05 04:16:5212#include "base/location.h"
[email protected]7ccb7072013-06-10 20:56:2813#include "base/message_loop/message_loop_proxy.h"
[email protected]b307bceb2011-11-17 07:49:5514#include "base/stl_util.h"
[email protected]afa339d72013-06-11 06:32:5115#include "base/strings/stringprintf.h"
[email protected]49c4cf852013-09-27 19:28:2416#include "base/sys_info.h"
[email protected]593cf3b2013-03-05 04:16:5217#include "base/task_runner_util.h"
18#include "base/threading/worker_pool.h"
[email protected]81836aed2013-07-09 23:41:1219#include "base/values.h"
[email protected]4ae73292011-11-15 05:20:1820#include "dbus/bus.h"
21#include "dbus/message.h"
[email protected]216ed0b2012-02-14 21:29:0622#include "dbus/object_path.h"
[email protected]4ae73292011-11-15 05:20:1823#include "dbus/object_proxy.h"
[email protected]81836aed2013-07-09 23:41:1224#include "dbus/values_util.h"
[email protected]4ae73292011-11-15 05:20:1825#include "third_party/cros_system_api/dbus/service_constants.h"
26
27namespace chromeos {
28
29namespace {
30
31const char* kDefaultMountOptions[] = {
32 "rw",
33 "nodev",
34 "noexec",
35 "nosuid",
[email protected]4ae73292011-11-15 05:20:1836};
37
38const char* kDefaultUnmountOptions[] = {
39 "force",
40};
41
[email protected]10795ae2012-10-10 07:33:4942const char kLazyUnmountOption[] = "lazy";
43
[email protected]dcad8fc2012-04-30 23:31:3344const char kMountLabelOption[] = "mountlabel";
45
[email protected]2321d282012-01-31 23:06:5946// Checks if retrieved media type is in boundaries of DeviceMediaType.
47bool IsValidMediaType(uint32 type) {
48 return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
49}
50
[email protected]2321d282012-01-31 23:06:5951// Translates enum used in cros-disks to enum used in Chrome.
52// Note that we could just do static_cast, but this is less sensitive to
53// changes in cros-disks.
54DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) {
55 if (!IsValidMediaType(media_type_uint32))
56 return DEVICE_TYPE_UNKNOWN;
57
58 cros_disks::DeviceMediaType media_type =
59 cros_disks::DeviceMediaType(media_type_uint32);
60
61 switch (media_type) {
62 case(cros_disks::DEVICE_MEDIA_UNKNOWN):
63 return DEVICE_TYPE_UNKNOWN;
64 case(cros_disks::DEVICE_MEDIA_USB):
65 return DEVICE_TYPE_USB;
66 case(cros_disks::DEVICE_MEDIA_SD):
67 return DEVICE_TYPE_SD;
68 case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
69 return DEVICE_TYPE_OPTICAL_DISC;
70 case(cros_disks::DEVICE_MEDIA_MOBILE):
71 return DEVICE_TYPE_MOBILE;
[email protected]f4ae40ac2012-05-04 21:57:0072 case(cros_disks::DEVICE_MEDIA_DVD):
73 return DEVICE_TYPE_DVD;
[email protected]2321d282012-01-31 23:06:5974 default:
75 return DEVICE_TYPE_UNKNOWN;
76 }
[email protected]4ae73292011-11-15 05:20:1877}
78
[email protected]d7760592014-05-16 07:57:5279bool ReadMountEntryFromDbus(dbus::MessageReader* reader, MountEntry* entry) {
80 uint32 error_code = 0;
81 std::string source_path;
82 uint32 mount_type = 0;
83 std::string mount_path;
84 if (!reader->PopUint32(&error_code) ||
85 !reader->PopString(&source_path) ||
86 !reader->PopUint32(&mount_type) ||
87 !reader->PopString(&mount_path)) {
88 return false;
89 }
90 *entry = MountEntry(static_cast<MountError>(error_code), source_path,
91 static_cast<MountType>(mount_type), mount_path);
92 return true;
93}
94
[email protected]4ae73292011-11-15 05:20:1895// The CrosDisksClient implementation.
96class CrosDisksClientImpl : public CrosDisksClient {
97 public:
[email protected]c5fd5362013-08-27 12:23:0498 CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
[email protected]4ae73292011-11-15 05:20:1899
100 // CrosDisksClient override.
101 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48102 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33103 const std::string& mount_label,
[email protected]5624a252013-07-04 03:17:53104 const base::Closure& callback,
105 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18106 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
107 cros_disks::kMount);
108 dbus::MessageWriter writer(&method_call);
109 writer.AppendString(source_path);
[email protected]b9f22d12012-04-25 21:46:48110 writer.AppendString(source_format);
[email protected]4ae73292011-11-15 05:20:18111 std::vector<std::string> mount_options(kDefaultMountOptions,
112 kDefaultMountOptions +
113 arraysize(kDefaultMountOptions));
[email protected]dcad8fc2012-04-30 23:31:33114 if (!mount_label.empty()) {
115 std::string mount_label_option = base::StringPrintf("%s=%s",
116 kMountLabelOption,
117 mount_label.c_str());
118 mount_options.push_back(mount_label_option);
119 }
[email protected]4ae73292011-11-15 05:20:18120 writer.AppendArrayOfStrings(mount_options);
121 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
122 base::Bind(&CrosDisksClientImpl::OnMount,
123 weak_ptr_factory_.GetWeakPtr(),
124 callback,
125 error_callback));
126 }
127
128 // CrosDisksClient override.
129 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49130 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39131 const base::Closure& callback,
132 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18133 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
134 cros_disks::kUnmount);
135 dbus::MessageWriter writer(&method_call);
136 writer.AppendString(device_path);
[email protected]10795ae2012-10-10 07:33:49137
138 std::vector<std::string> unmount_options(
139 kDefaultUnmountOptions,
140 kDefaultUnmountOptions + arraysize(kDefaultUnmountOptions));
141 if (options == UNMOUNT_OPTIONS_LAZY)
142 unmount_options.push_back(kLazyUnmountOption);
143
[email protected]4ae73292011-11-15 05:20:18144 writer.AppendArrayOfStrings(unmount_options);
145 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
146 base::Bind(&CrosDisksClientImpl::OnUnmount,
147 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18148 callback,
149 error_callback));
150 }
151
152 // CrosDisksClient override.
153 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35154 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53155 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18156 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
157 cros_disks::kEnumerateAutoMountableDevices);
158 proxy_->CallMethod(
159 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
160 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
161 weak_ptr_factory_.GetWeakPtr(),
162 callback,
163 error_callback));
164 }
165
166 // CrosDisksClient override.
[email protected]d7760592014-05-16 07:57:52167 virtual void EnumerateMountEntries(
168 const EnumerateMountEntriesCallback& callback,
169 const base::Closure& error_callback) OVERRIDE {
170 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
171 cros_disks::kEnumerateMountEntries);
172 proxy_->CallMethod(
173 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
174 base::Bind(&CrosDisksClientImpl::OnEnumerateMountEntries,
175 weak_ptr_factory_.GetWeakPtr(),
176 callback,
177 error_callback));
178 }
179
180 // CrosDisksClient override.
[email protected]f026c0f2014-05-06 21:52:35181 virtual void Format(const std::string& device_path,
182 const std::string& filesystem,
183 const base::Closure& callback,
184 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18185 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
[email protected]f026c0f2014-05-06 21:52:35186 cros_disks::kFormat);
[email protected]4ae73292011-11-15 05:20:18187 dbus::MessageWriter writer(&method_call);
188 writer.AppendString(device_path);
189 writer.AppendString(filesystem);
[email protected]f026c0f2014-05-06 21:52:35190 // No format option is currently specified, but we can later use this
191 // argument to specify options for the format operation.
192 std::vector<std::string> format_options;
193 writer.AppendArrayOfStrings(format_options);
[email protected]4ae73292011-11-15 05:20:18194 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
[email protected]f026c0f2014-05-06 21:52:35195 base::Bind(&CrosDisksClientImpl::OnFormat,
[email protected]4ae73292011-11-15 05:20:18196 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18197 callback,
198 error_callback));
199 }
200
201 // CrosDisksClient override.
[email protected]4a404e52012-04-11 02:25:35202 virtual void GetDeviceProperties(
203 const std::string& device_path,
204 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53205 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18206 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
207 cros_disks::kGetDeviceProperties);
208 dbus::MessageWriter writer(&method_call);
209 writer.AppendString(device_path);
210 proxy_->CallMethod(&method_call,
211 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
212 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
213 weak_ptr_factory_.GetWeakPtr(),
214 device_path,
215 callback,
216 error_callback));
217 }
218
219 // CrosDisksClient override.
[email protected]a0278d52014-05-06 03:36:15220 virtual void SetMountEventHandler(
221 const MountEventHandler& mount_event_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18222 static const SignalEventTuple kSignalEventTuples[] = {
[email protected]e3c1fc92012-11-15 00:56:46223 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
224 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
225 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
226 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
227 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
228 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
[email protected]4ae73292011-11-15 05:20:18229 };
230 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
231
232 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
233 proxy_->ConnectToSignal(
234 cros_disks::kCrosDisksInterface,
235 kSignalEventTuples[i].signal_name,
236 base::Bind(&CrosDisksClientImpl::OnMountEvent,
237 weak_ptr_factory_.GetWeakPtr(),
238 kSignalEventTuples[i].event_type,
239 mount_event_handler),
240 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
241 weak_ptr_factory_.GetWeakPtr()));
242 }
[email protected]a0278d52014-05-06 03:36:15243 }
244
245 // CrosDisksClient override.
246 virtual void SetMountCompletedHandler(
247 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18248 proxy_->ConnectToSignal(
249 cros_disks::kCrosDisksInterface,
[email protected]b3e3f492011-11-18 18:46:00250 cros_disks::kMountCompleted,
[email protected]4ae73292011-11-15 05:20:18251 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
252 weak_ptr_factory_.GetWeakPtr(),
[email protected]85b95a2012012-08-07 18:57:27253 mount_completed_handler),
[email protected]4ae73292011-11-15 05:20:18254 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
255 weak_ptr_factory_.GetWeakPtr()));
256 }
257
[email protected]a0278d52014-05-06 03:36:15258 // CrosDisksClient override.
259 virtual void SetFormatCompletedHandler(
260 const FormatCompletedHandler& format_completed_handler) OVERRIDE {
261 proxy_->ConnectToSignal(
262 cros_disks::kCrosDisksInterface,
263 cros_disks::kFormatCompleted,
264 base::Bind(&CrosDisksClientImpl::OnFormatCompleted,
265 weak_ptr_factory_.GetWeakPtr(),
266 format_completed_handler),
267 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
268 weak_ptr_factory_.GetWeakPtr()));
269 }
270
[email protected]c5fd5362013-08-27 12:23:04271 protected:
272 virtual void Init(dbus::Bus* bus) OVERRIDE {
273 proxy_ = bus->GetObjectProxy(
274 cros_disks::kCrosDisksServiceName,
275 dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
276 }
277
[email protected]4ae73292011-11-15 05:20:18278 private:
279 // A struct to contain a pair of signal name and mount event type.
[email protected]a0278d52014-05-06 03:36:15280 // Used by SetMountEventHandler.
[email protected]4ae73292011-11-15 05:20:18281 struct SignalEventTuple {
282 const char *signal_name;
283 MountEventType event_type;
284 };
285
286 // Handles the result of Mount and calls |callback| or |error_callback|.
[email protected]5624a252013-07-04 03:17:53287 void OnMount(const base::Closure& callback,
288 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18289 dbus::Response* response) {
290 if (!response) {
291 error_callback.Run();
292 return;
293 }
294 callback.Run();
295 }
296
[email protected]d7760592014-05-16 07:57:52297 // Handles the result of Unmount and calls |callback| or |error_callback|.
[email protected]ffdcc7a9c2013-07-02 06:59:39298 void OnUnmount(const base::Closure& callback,
299 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18300 dbus::Response* response) {
301 if (!response) {
[email protected]ffdcc7a9c2013-07-02 06:59:39302 error_callback.Run();
[email protected]4ae73292011-11-15 05:20:18303 return;
304 }
[email protected]ddcb18e2013-09-19 07:17:28305
306 // Temporarly allow Unmount method to report failure both by setting dbus
307 // error (in which case response is not set) and by returning mount error
308 // different from MOUNT_ERROR_NONE. This is done so we can change Unmount
309 // method to return mount error (http://crbug.com/288974) without breaking
310 // Chrome.
311 // TODO(tbarzic): When Unmount implementation is changed on cros disks side,
312 // make this fail if reader is not able to read the error code value from
313 // the response.
314 dbus::MessageReader reader(response);
[email protected]a0278d52014-05-06 03:36:15315 uint32 error_code = 0;
[email protected]ddcb18e2013-09-19 07:17:28316 if (reader.PopUint32(&error_code) &&
317 static_cast<MountError>(error_code) != MOUNT_ERROR_NONE) {
318 error_callback.Run();
319 return;
320 }
321
[email protected]ffdcc7a9c2013-07-02 06:59:39322 callback.Run();
[email protected]4ae73292011-11-15 05:20:18323 }
324
325 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
326 // |error_callback|.
327 void OnEnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35328 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53329 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18330 dbus::Response* response) {
331 if (!response) {
332 error_callback.Run();
333 return;
334 }
335 dbus::MessageReader reader(response);
336 std::vector<std::string> device_paths;
337 if (!reader.PopArrayOfStrings(&device_paths)) {
338 LOG(ERROR) << "Invalid response: " << response->ToString();
339 error_callback.Run();
340 return;
341 }
342 callback.Run(device_paths);
343 }
344
[email protected]d7760592014-05-16 07:57:52345 // Handles the result of EnumerateMountEntries and calls |callback| or
346 // |error_callback|.
347 void OnEnumerateMountEntries(
348 const EnumerateMountEntriesCallback& callback,
349 const base::Closure& error_callback,
350 dbus::Response* response) {
351 if (!response) {
352 error_callback.Run();
353 return;
354 }
355
356 dbus::MessageReader reader(response);
357 dbus::MessageReader array_reader(NULL);
358 if (!reader.PopArray(&array_reader)) {
359 LOG(ERROR) << "Invalid response: " << response->ToString();
360 error_callback.Run();
361 return;
362 }
363
364 std::vector<MountEntry> entries;
365 while (array_reader.HasMoreData()) {
366 MountEntry entry;
367 dbus::MessageReader sub_reader(NULL);
368 if (!array_reader.PopStruct(&sub_reader) ||
369 !ReadMountEntryFromDbus(&sub_reader, &entry)) {
370 LOG(ERROR) << "Invalid response: " << response->ToString();
371 error_callback.Run();
372 return;
373 }
374 entries.push_back(entry);
375 }
376 callback.Run(entries);
377 }
378
[email protected]f026c0f2014-05-06 21:52:35379 // Handles the result of Format and calls |callback| or |error_callback|.
380 void OnFormat(const base::Closure& callback,
381 const base::Closure& error_callback,
382 dbus::Response* response) {
[email protected]4ae73292011-11-15 05:20:18383 if (!response) {
384 error_callback.Run();
385 return;
386 }
[email protected]f026c0f2014-05-06 21:52:35387 callback.Run();
[email protected]4ae73292011-11-15 05:20:18388 }
389
390 // Handles the result of GetDeviceProperties and calls |callback| or
391 // |error_callback|.
392 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35393 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53394 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18395 dbus::Response* response) {
396 if (!response) {
397 error_callback.Run();
398 return;
399 }
400 DiskInfo disk(device_path, response);
401 callback.Run(disk);
402 }
403
404 // Handles mount event signals and calls |handler|.
405 void OnMountEvent(MountEventType event_type,
406 MountEventHandler handler,
407 dbus::Signal* signal) {
408 dbus::MessageReader reader(signal);
409 std::string device;
410 if (!reader.PopString(&device)) {
411 LOG(ERROR) << "Invalid signal: " << signal->ToString();
412 return;
413 }
414 handler.Run(event_type, device);
415 }
416
417 // Handles MountCompleted signal and calls |handler|.
418 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
419 dbus::MessageReader reader(signal);
[email protected]d7760592014-05-16 07:57:52420 MountEntry entry;
421 if (!ReadMountEntryFromDbus(&reader, &entry)) {
[email protected]4ae73292011-11-15 05:20:18422 LOG(ERROR) << "Invalid signal: " << signal->ToString();
423 return;
424 }
[email protected]d7760592014-05-16 07:57:52425 handler.Run(entry);
[email protected]4ae73292011-11-15 05:20:18426 }
427
[email protected]a0278d52014-05-06 03:36:15428 // Handles FormatCompleted signal and calls |handler|.
429 void OnFormatCompleted(FormatCompletedHandler handler, dbus::Signal* signal) {
430 dbus::MessageReader reader(signal);
431 uint32 error_code = 0;
432 std::string device_path;
433 if (!reader.PopUint32(&error_code) || !reader.PopString(&device_path)) {
434 LOG(ERROR) << "Invalid signal: " << signal->ToString();
435 return;
436 }
437 handler.Run(static_cast<FormatError>(error_code), device_path);
438 }
439
[email protected]4ae73292011-11-15 05:20:18440 // Handles the result of signal connection setup.
441 void OnSignalConnected(const std::string& interface,
442 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43443 bool succeeded) {
444 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18445 signal << " failed.";
446 }
447
448 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16449
450 // Note: This should remain the last member so it'll be destroyed and
451 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18452 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
453
454 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
455};
456
457// A stub implementaion of CrosDisksClient.
458class CrosDisksClientStubImpl : public CrosDisksClient {
459 public:
[email protected]593cf3b2013-03-05 04:16:52460 CrosDisksClientStubImpl()
[email protected]637c17b82013-04-26 08:13:10461 : weak_ptr_factory_(this) {}
[email protected]593cf3b2013-03-05 04:16:52462
[email protected]4ae73292011-11-15 05:20:18463 virtual ~CrosDisksClientStubImpl() {}
464
[email protected]593cf3b2013-03-05 04:16:52465 // CrosDisksClient overrides:
[email protected]c5fd5362013-08-27 12:23:04466 virtual void Init(dbus::Bus* bus) OVERRIDE {}
[email protected]4ae73292011-11-15 05:20:18467 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48468 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33469 const std::string& mount_label,
[email protected]5624a252013-07-04 03:17:53470 const base::Closure& callback,
471 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52472 // This stub implementation only accepts archive mount requests.
[email protected]44ad4ec2013-07-12 07:56:16473 const MountType type = MOUNT_TYPE_ARCHIVE;
[email protected]593cf3b2013-03-05 04:16:52474
475 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
476 base::FilePath::FromUTF8Unsafe(mount_label));
477
[email protected]be0ed642013-03-07 06:39:32478 // Already mounted path.
479 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
480 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
481 std::string(), callback);
482 return;
483 }
484
[email protected]593cf3b2013-03-05 04:16:52485 // Perform fake mount.
486 base::PostTaskAndReplyWithResult(
[email protected]144b6c42013-06-14 07:30:38487 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
[email protected]593cf3b2013-03-05 04:16:52488 FROM_HERE,
[email protected]144b6c42013-06-14 07:30:38489 base::Bind(&PerformFakeMount, source_path, mounted_path),
[email protected]593cf3b2013-03-05 04:16:52490 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
491 weak_ptr_factory_.GetWeakPtr(),
492 source_path,
493 type,
494 callback,
495 mounted_path));
496 }
497
[email protected]4ae73292011-11-15 05:20:18498 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49499 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39500 const base::Closure& callback,
501 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52502 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32503 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]ffdcc7a9c2013-07-02 06:59:39504 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
[email protected]593cf3b2013-03-05 04:16:52505 return;
506 }
507
[email protected]be0ed642013-03-07 06:39:32508 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52509
510 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32511 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52512 FROM_HERE,
[email protected]dd3aa792013-07-16 19:10:23513 base::Bind(base::IgnoreResult(&base::DeleteFile),
[email protected]be0ed642013-03-07 06:39:32514 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52515 true /* recursive */),
[email protected]ffdcc7a9c2013-07-02 06:59:39516 callback,
[email protected]593cf3b2013-03-05 04:16:52517 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52518 }
519
[email protected]4ae73292011-11-15 05:20:18520 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35521 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53522 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52523 std::vector<std::string> device_paths;
524 base::MessageLoopProxy::current()->PostTask(
525 FROM_HERE, base::Bind(callback, device_paths));
526 }
527
[email protected]d7760592014-05-16 07:57:52528 virtual void EnumerateMountEntries(
529 const EnumerateMountEntriesCallback& callback,
530 const base::Closure& error_callback) OVERRIDE {
531 std::vector<MountEntry> entries;
532 base::MessageLoopProxy::current()->PostTask(
533 FROM_HERE, base::Bind(callback, entries));
534 }
535
[email protected]f026c0f2014-05-06 21:52:35536 virtual void Format(const std::string& device_path,
537 const std::string& filesystem,
538 const base::Closure& callback,
539 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52540 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
541 }
542
[email protected]4a404e52012-04-11 02:25:35543 virtual void GetDeviceProperties(
544 const std::string& device_path,
545 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53546 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52547 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
548 }
549
[email protected]a0278d52014-05-06 03:36:15550 virtual void SetMountEventHandler(
551 const MountEventHandler& mount_event_handler) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52552 mount_event_handler_ = mount_event_handler;
[email protected]a0278d52014-05-06 03:36:15553 }
554
555 virtual void SetMountCompletedHandler(
556 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52557 mount_completed_handler_ = mount_completed_handler;
558 }
[email protected]4ae73292011-11-15 05:20:18559
[email protected]a0278d52014-05-06 03:36:15560 virtual void SetFormatCompletedHandler(
561 const FormatCompletedHandler& format_completed_handler) OVERRIDE {
562 format_completed_handler_ = format_completed_handler;
563 }
564
[email protected]4ae73292011-11-15 05:20:18565 private:
[email protected]593cf3b2013-03-05 04:16:52566 // Performs file actions for Mount().
567 static MountError PerformFakeMount(const std::string& source_path,
568 const base::FilePath& mounted_path) {
569 // Check the source path exists.
[email protected]7567484142013-07-11 17:36:07570 if (!base::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
[email protected]593cf3b2013-03-05 04:16:52571 DLOG(ERROR) << "Source does not exist at " << source_path;
572 return MOUNT_ERROR_INVALID_PATH;
573 }
574
575 // Just create an empty directory and shows it as the mounted directory.
[email protected]426d1c92013-12-03 20:08:54576 if (!base::CreateDirectory(mounted_path)) {
[email protected]593cf3b2013-03-05 04:16:52577 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
578 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
579 }
580
581 // Put a dummy file.
582 const base::FilePath dummy_file_path =
583 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
584 const std::string dummy_file_content = "This is a dummy file.";
[email protected]e5c2a22e2014-03-06 20:42:30585 const int write_result = base::WriteFile(
[email protected]593cf3b2013-03-05 04:16:52586 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
587 if (write_result != static_cast<int>(dummy_file_content.size())) {
588 DLOG(ERROR) << "Failed to put a dummy file at "
589 << dummy_file_path.value();
590 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
591 }
592
593 return MOUNT_ERROR_NONE;
594 }
595
596 // Part of Mount() implementation.
597 void ContinueMount(const std::string& source_path,
598 MountType type,
[email protected]5624a252013-07-04 03:17:53599 const base::Closure& callback,
[email protected]593cf3b2013-03-05 04:16:52600 const base::FilePath& mounted_path,
601 MountError mount_error) {
602 if (mount_error != MOUNT_ERROR_NONE) {
603 FinishMount(mount_error, source_path, type, std::string(), callback);
604 return;
605 }
[email protected]be0ed642013-03-07 06:39:32606 mounted_to_source_path_map_[mounted_path.value()] = source_path;
[email protected]593cf3b2013-03-05 04:16:52607 FinishMount(MOUNT_ERROR_NONE, source_path, type,
608 mounted_path.AsUTF8Unsafe(), callback);
609 }
610
611 // Runs |callback| and sends MountCompleted signal.
612 // Part of Mount() implementation.
613 void FinishMount(MountError error,
614 const std::string& source_path,
615 MountType type,
616 const std::string& mounted_path,
[email protected]5624a252013-07-04 03:17:53617 const base::Closure& callback) {
[email protected]593cf3b2013-03-05 04:16:52618 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
619 if (!mount_completed_handler_.is_null()) {
620 base::MessageLoopProxy::current()->PostTask(
621 FROM_HERE,
622 base::Bind(mount_completed_handler_,
[email protected]d7760592014-05-16 07:57:52623 MountEntry(error, source_path, type, mounted_path)));
[email protected]593cf3b2013-03-05 04:16:52624 }
625 }
626
[email protected]be0ed642013-03-07 06:39:32627 // Mounted path to source path map.
628 std::map<std::string, std::string> mounted_to_source_path_map_;
[email protected]593cf3b2013-03-05 04:16:52629
630 MountEventHandler mount_event_handler_;
631 MountCompletedHandler mount_completed_handler_;
[email protected]a0278d52014-05-06 03:36:15632 FormatCompletedHandler format_completed_handler_;
[email protected]593cf3b2013-03-05 04:16:52633
634 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
635
[email protected]4ae73292011-11-15 05:20:18636 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
637};
638
[email protected]85b95a2012012-08-07 18:57:27639} // namespace
[email protected]4ae73292011-11-15 05:20:18640
641////////////////////////////////////////////////////////////////////////////////
642// DiskInfo
643
644DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
645 : device_path_(device_path),
646 is_drive_(false),
647 has_media_(false),
648 on_boot_device_(false),
[email protected]79ed457b2014-07-22 04:07:26649 on_removable_device_(false),
[email protected]2321d282012-01-31 23:06:59650 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18651 total_size_in_bytes_(0),
652 is_read_only_(false),
653 is_hidden_(true) {
654 InitializeFromResponse(response);
655}
656
657DiskInfo::~DiskInfo() {
658}
659
[email protected]85b95a2012012-08-07 18:57:27660// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18661// Below is an example of |response|'s raw message (long string is ellipsized).
662//
663//
664// message_type: MESSAGE_METHOD_RETURN
665// destination: :1.8
666// sender: :1.16
667// signature: a{sv}
668// serial: 96
669// reply_serial: 267
670//
671// array [
672// dict entry {
673// string "DeviceFile"
674// variant string "/dev/sdb"
675// }
676// dict entry {
677// string "DeviceIsDrive"
678// variant bool true
679// }
680// dict entry {
681// string "DeviceIsMediaAvailable"
682// variant bool true
683// }
684// dict entry {
685// string "DeviceIsMounted"
686// variant bool false
687// }
688// dict entry {
689// string "DeviceIsOnBootDevice"
690// variant bool false
691// }
692// dict entry {
[email protected]79ed457b2014-07-22 04:07:26693// string "DeviceIsOnRemovableDevice"
694// variant bool true
695// }
696// dict entry {
[email protected]4ae73292011-11-15 05:20:18697// string "DeviceIsReadOnly"
698// variant bool false
699// }
700// dict entry {
701// string "DeviceIsVirtual"
702// variant bool false
703// }
704// dict entry {
705// string "DeviceMediaType"
706// variant uint32 1
707// }
708// dict entry {
709// string "DeviceMountPaths"
710// variant array [
711// ]
712// }
713// dict entry {
714// string "DevicePresentationHide"
715// variant bool true
716// }
717// dict entry {
718// string "DeviceSize"
719// variant uint64 7998537728
720// }
721// dict entry {
722// string "DriveIsRotational"
723// variant bool false
724// }
725// dict entry {
[email protected]202e9fee2012-09-13 20:21:29726// string "VendorId"
727// variant string "18d1"
728// }
729// dict entry {
730// string "VendorName"
731// variant string "Google Inc."
732// }
733// dict entry {
734// string "ProductId"
735// variant string "4e11"
736// }
737// dict entry {
738// string "ProductName"
739// variant string "Nexus One"
740// }
741// dict entry {
[email protected]4ae73292011-11-15 05:20:18742// string "DriveModel"
743// variant string "TransMemory"
744// }
745// dict entry {
746// string "IdLabel"
747// variant string ""
748// }
749// dict entry {
750// string "IdUuid"
751// variant string ""
752// }
753// dict entry {
754// string "NativePath"
755// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
756// }
757// ]
758void DiskInfo::InitializeFromResponse(dbus::Response* response) {
[email protected]81836aed2013-07-09 23:41:12759 dbus::MessageReader reader(response);
760 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
761 base::DictionaryValue* properties = NULL;
762 if (!value || !value->GetAsDictionary(&properties))
[email protected]4ae73292011-11-15 05:20:18763 return;
[email protected]4ae73292011-11-15 05:20:18764
[email protected]81836aed2013-07-09 23:41:12765 properties->GetBooleanWithoutPathExpansion(
766 cros_disks::kDeviceIsDrive, &is_drive_);
767 properties->GetBooleanWithoutPathExpansion(
768 cros_disks::kDeviceIsReadOnly, &is_read_only_);
769 properties->GetBooleanWithoutPathExpansion(
770 cros_disks::kDevicePresentationHide, &is_hidden_);
771 properties->GetBooleanWithoutPathExpansion(
772 cros_disks::kDeviceIsMediaAvailable, &has_media_);
773 properties->GetBooleanWithoutPathExpansion(
774 cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
[email protected]79ed457b2014-07-22 04:07:26775 properties->GetBooleanWithoutPathExpansion(
776 cros_disks::kDeviceIsOnRemovableDevice, &on_removable_device_);
[email protected]81836aed2013-07-09 23:41:12777 properties->GetStringWithoutPathExpansion(
778 cros_disks::kNativePath, &system_path_);
779 properties->GetStringWithoutPathExpansion(
780 cros_disks::kDeviceFile, &file_path_);
781 properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
782 properties->GetStringWithoutPathExpansion(
783 cros_disks::kVendorName, &vendor_name_);
784 properties->GetStringWithoutPathExpansion(
785 cros_disks::kProductId, &product_id_);
786 properties->GetStringWithoutPathExpansion(
787 cros_disks::kProductName, &product_name_);
788 properties->GetStringWithoutPathExpansion(
789 cros_disks::kDriveModel, &drive_model_);
790 properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
791 properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
[email protected]2321d282012-01-31 23:06:59792
[email protected]81836aed2013-07-09 23:41:12793 // dbus::PopDataAsValue() pops uint64 as double.
794 // The top 11 bits of uint64 are dropped by the use of double. But, this works
795 // unless the size exceeds 8 PB.
796 double device_size_double = 0;
797 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
798 &device_size_double))
799 total_size_in_bytes_ = device_size_double;
800
801 // dbus::PopDataAsValue() pops uint32 as double.
802 double media_type_double = 0;
803 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
804 &media_type_double))
805 device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
806
807 base::ListValue* mount_paths = NULL;
808 if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
809 &mount_paths))
810 mount_paths->GetString(0, &mount_path_);
[email protected]4ae73292011-11-15 05:20:18811}
812
813////////////////////////////////////////////////////////////////////////////////
814// CrosDisksClient
815
816CrosDisksClient::CrosDisksClient() {}
817
818CrosDisksClient::~CrosDisksClient() {}
819
820// static
[email protected]c5fd5362013-08-27 12:23:04821CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
[email protected]e8db03d62012-03-31 04:08:38822 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]c5fd5362013-08-27 12:23:04823 return new CrosDisksClientImpl();
[email protected]e8db03d62012-03-31 04:08:38824 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
825 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18826}
827
[email protected]a5a8b412013-03-04 15:03:11828// static
829base::FilePath CrosDisksClient::GetArchiveMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24830 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11831 FILE_PATH_LITERAL("/media/archive") :
832 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
833}
834
835// static
836base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24837 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11838 FILE_PATH_LITERAL("/media/removable") :
839 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
840}
841
[email protected]4ae73292011-11-15 05:20:18842} // namespace chromeos