blob: 915e4ecc95105491f70b4681bbe571e466bda914 [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]a5a8b412013-03-04 15:03:1110#include "base/chromeos/chromeos_version.h"
[email protected]593cf3b2013-03-05 04:16:5211#include "base/file_util.h"
[email protected]a5a8b412013-03-04 15:03:1112#include "base/files/file_path.h"
[email protected]593cf3b2013-03-05 04:16:5213#include "base/location.h"
[email protected]7ccb7072013-06-10 20:56:2814#include "base/message_loop/message_loop_proxy.h"
[email protected]b307bceb2011-11-17 07:49:5515#include "base/stl_util.h"
[email protected]afa339d72013-06-11 06:32:5116#include "base/strings/stringprintf.h"
[email protected]593cf3b2013-03-05 04:16:5217#include "base/task_runner_util.h"
18#include "base/threading/worker_pool.h"
[email protected]4ae73292011-11-15 05:20:1819#include "dbus/bus.h"
20#include "dbus/message.h"
[email protected]216ed0b2012-02-14 21:29:0621#include "dbus/object_path.h"
[email protected]4ae73292011-11-15 05:20:1822#include "dbus/object_proxy.h"
23#include "third_party/cros_system_api/dbus/service_constants.h"
24
25namespace chromeos {
26
27namespace {
28
29const char* kDefaultMountOptions[] = {
30 "rw",
31 "nodev",
32 "noexec",
33 "nosuid",
[email protected]4ae73292011-11-15 05:20:1834};
35
36const char* kDefaultUnmountOptions[] = {
37 "force",
38};
39
[email protected]10795ae2012-10-10 07:33:4940const char kLazyUnmountOption[] = "lazy";
41
[email protected]dcad8fc2012-04-30 23:31:3342const char kMountLabelOption[] = "mountlabel";
43
[email protected]2321d282012-01-31 23:06:5944// Checks if retrieved media type is in boundaries of DeviceMediaType.
45bool IsValidMediaType(uint32 type) {
46 return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
47}
48
49
50// Translates enum used in cros-disks to enum used in Chrome.
51// Note that we could just do static_cast, but this is less sensitive to
52// changes in cros-disks.
53DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) {
54 if (!IsValidMediaType(media_type_uint32))
55 return DEVICE_TYPE_UNKNOWN;
56
57 cros_disks::DeviceMediaType media_type =
58 cros_disks::DeviceMediaType(media_type_uint32);
59
60 switch (media_type) {
61 case(cros_disks::DEVICE_MEDIA_UNKNOWN):
62 return DEVICE_TYPE_UNKNOWN;
63 case(cros_disks::DEVICE_MEDIA_USB):
64 return DEVICE_TYPE_USB;
65 case(cros_disks::DEVICE_MEDIA_SD):
66 return DEVICE_TYPE_SD;
67 case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
68 return DEVICE_TYPE_OPTICAL_DISC;
69 case(cros_disks::DEVICE_MEDIA_MOBILE):
70 return DEVICE_TYPE_MOBILE;
[email protected]f4ae40ac2012-05-04 21:57:0071 case(cros_disks::DEVICE_MEDIA_DVD):
72 return DEVICE_TYPE_DVD;
[email protected]2321d282012-01-31 23:06:5973 default:
74 return DEVICE_TYPE_UNKNOWN;
75 }
[email protected]4ae73292011-11-15 05:20:1876}
77
78// Pops a bool value when |reader| is not NULL.
79// Returns true when a value is popped, false otherwise.
80bool MaybePopBool(dbus::MessageReader* reader, bool* value) {
81 if (!reader)
82 return false;
83 return reader->PopBool(value);
84}
85
86// Pops a string value when |reader| is not NULL.
87// Returns true when a value is popped, false otherwise.
88bool MaybePopString(dbus::MessageReader* reader, std::string* value) {
89 if (!reader)
90 return false;
91 return reader->PopString(value);
92}
93
[email protected]2321d282012-01-31 23:06:5994// Pops a uint32 value when |reader| is not NULL.
95// Returns true when a value is popped, false otherwise.
96bool MaybePopUint32(dbus::MessageReader* reader, uint32* value) {
97 if (!reader)
98 return false;
99
100 return reader->PopUint32(value);
101}
102
[email protected]4ae73292011-11-15 05:20:18103// Pops a uint64 value when |reader| is not NULL.
104// Returns true when a value is popped, false otherwise.
105bool MaybePopUint64(dbus::MessageReader* reader, uint64* value) {
106 if (!reader)
107 return false;
108 return reader->PopUint64(value);
109}
110
111// Pops an array of strings when |reader| is not NULL.
112// Returns true when an array is popped, false otherwise.
113bool MaybePopArrayOfStrings(dbus::MessageReader* reader,
114 std::vector<std::string>* value) {
115 if (!reader)
116 return false;
117 return reader->PopArrayOfStrings(value);
118}
119
120// The CrosDisksClient implementation.
121class CrosDisksClientImpl : public CrosDisksClient {
122 public:
123 explicit CrosDisksClientImpl(dbus::Bus* bus)
[email protected]216ed0b2012-02-14 21:29:06124 : proxy_(bus->GetObjectProxy(
125 cros_disks::kCrosDisksServiceName,
126 dbus::ObjectPath(cros_disks::kCrosDisksServicePath))),
[email protected]4ae73292011-11-15 05:20:18127 weak_ptr_factory_(this) {
128 }
129
130 // CrosDisksClient override.
131 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48132 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33133 const std::string& mount_label,
[email protected]4ae73292011-11-15 05:20:18134 MountType type,
[email protected]4a404e52012-04-11 02:25:35135 const MountCallback& callback,
136 const ErrorCallback& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18137 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
138 cros_disks::kMount);
139 dbus::MessageWriter writer(&method_call);
140 writer.AppendString(source_path);
[email protected]b9f22d12012-04-25 21:46:48141 writer.AppendString(source_format);
[email protected]4ae73292011-11-15 05:20:18142 std::vector<std::string> mount_options(kDefaultMountOptions,
143 kDefaultMountOptions +
144 arraysize(kDefaultMountOptions));
[email protected]dcad8fc2012-04-30 23:31:33145 if (!mount_label.empty()) {
146 std::string mount_label_option = base::StringPrintf("%s=%s",
147 kMountLabelOption,
148 mount_label.c_str());
149 mount_options.push_back(mount_label_option);
150 }
[email protected]4ae73292011-11-15 05:20:18151 writer.AppendArrayOfStrings(mount_options);
152 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
153 base::Bind(&CrosDisksClientImpl::OnMount,
154 weak_ptr_factory_.GetWeakPtr(),
155 callback,
156 error_callback));
157 }
158
159 // CrosDisksClient override.
160 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49161 UnmountOptions options,
[email protected]4a404e52012-04-11 02:25:35162 const UnmountCallback& callback,
[email protected]10795ae2012-10-10 07:33:49163 const UnmountCallback& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18164 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
165 cros_disks::kUnmount);
166 dbus::MessageWriter writer(&method_call);
167 writer.AppendString(device_path);
[email protected]10795ae2012-10-10 07:33:49168
169 std::vector<std::string> unmount_options(
170 kDefaultUnmountOptions,
171 kDefaultUnmountOptions + arraysize(kDefaultUnmountOptions));
172 if (options == UNMOUNT_OPTIONS_LAZY)
173 unmount_options.push_back(kLazyUnmountOption);
174
[email protected]4ae73292011-11-15 05:20:18175 writer.AppendArrayOfStrings(unmount_options);
176 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
177 base::Bind(&CrosDisksClientImpl::OnUnmount,
178 weak_ptr_factory_.GetWeakPtr(),
179 device_path,
180 callback,
181 error_callback));
182 }
183
184 // CrosDisksClient override.
185 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35186 const EnumerateAutoMountableDevicesCallback& callback,
187 const ErrorCallback& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18188 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
189 cros_disks::kEnumerateAutoMountableDevices);
190 proxy_->CallMethod(
191 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
192 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
193 weak_ptr_factory_.GetWeakPtr(),
194 callback,
195 error_callback));
196 }
197
198 // CrosDisksClient override.
199 virtual void FormatDevice(const std::string& device_path,
200 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35201 const FormatDeviceCallback& callback,
202 const ErrorCallback& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18203 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
204 cros_disks::kFormatDevice);
205 dbus::MessageWriter writer(&method_call);
206 writer.AppendString(device_path);
207 writer.AppendString(filesystem);
208 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
209 base::Bind(&CrosDisksClientImpl::OnFormatDevice,
210 weak_ptr_factory_.GetWeakPtr(),
211 device_path,
212 callback,
213 error_callback));
214 }
215
216 // CrosDisksClient override.
[email protected]4a404e52012-04-11 02:25:35217 virtual void GetDeviceProperties(
218 const std::string& device_path,
219 const GetDevicePropertiesCallback& callback,
220 const ErrorCallback& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18221 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
222 cros_disks::kGetDeviceProperties);
223 dbus::MessageWriter writer(&method_call);
224 writer.AppendString(device_path);
225 proxy_->CallMethod(&method_call,
226 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
227 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
228 weak_ptr_factory_.GetWeakPtr(),
229 device_path,
230 callback,
231 error_callback));
232 }
233
234 // CrosDisksClient override.
235 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35236 const MountEventHandler& mount_event_handler,
237 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18238 static const SignalEventTuple kSignalEventTuples[] = {
[email protected]e3c1fc92012-11-15 00:56:46239 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
240 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
241 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
242 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
243 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
244 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
245 { cros_disks::kFormattingFinished, CROS_DISKS_FORMATTING_FINISHED },
[email protected]4ae73292011-11-15 05:20:18246 };
247 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
248
249 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
250 proxy_->ConnectToSignal(
251 cros_disks::kCrosDisksInterface,
252 kSignalEventTuples[i].signal_name,
253 base::Bind(&CrosDisksClientImpl::OnMountEvent,
254 weak_ptr_factory_.GetWeakPtr(),
255 kSignalEventTuples[i].event_type,
256 mount_event_handler),
257 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
258 weak_ptr_factory_.GetWeakPtr()));
259 }
260 proxy_->ConnectToSignal(
261 cros_disks::kCrosDisksInterface,
[email protected]b3e3f492011-11-18 18:46:00262 cros_disks::kMountCompleted,
[email protected]4ae73292011-11-15 05:20:18263 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
264 weak_ptr_factory_.GetWeakPtr(),
[email protected]85b95a2012012-08-07 18:57:27265 mount_completed_handler),
[email protected]4ae73292011-11-15 05:20:18266 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
267 weak_ptr_factory_.GetWeakPtr()));
268 }
269
270 private:
271 // A struct to contain a pair of signal name and mount event type.
272 // Used by SetUpConnections.
273 struct SignalEventTuple {
274 const char *signal_name;
275 MountEventType event_type;
276 };
277
278 // Handles the result of Mount and calls |callback| or |error_callback|.
[email protected]4a404e52012-04-11 02:25:35279 void OnMount(const MountCallback& callback,
280 const ErrorCallback& error_callback,
[email protected]4ae73292011-11-15 05:20:18281 dbus::Response* response) {
282 if (!response) {
283 error_callback.Run();
284 return;
285 }
286 callback.Run();
287 }
288
289 // Handles the result of Unount and calls |callback| or |error_callback|.
290 void OnUnmount(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35291 const UnmountCallback& callback,
[email protected]10795ae2012-10-10 07:33:49292 const UnmountCallback& error_callback,
[email protected]4ae73292011-11-15 05:20:18293 dbus::Response* response) {
294 if (!response) {
[email protected]10795ae2012-10-10 07:33:49295 error_callback.Run(device_path);
[email protected]4ae73292011-11-15 05:20:18296 return;
297 }
298 callback.Run(device_path);
299 }
300
301 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
302 // |error_callback|.
303 void OnEnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35304 const EnumerateAutoMountableDevicesCallback& callback,
305 const ErrorCallback& error_callback,
[email protected]4ae73292011-11-15 05:20:18306 dbus::Response* response) {
307 if (!response) {
308 error_callback.Run();
309 return;
310 }
311 dbus::MessageReader reader(response);
312 std::vector<std::string> device_paths;
313 if (!reader.PopArrayOfStrings(&device_paths)) {
314 LOG(ERROR) << "Invalid response: " << response->ToString();
315 error_callback.Run();
316 return;
317 }
318 callback.Run(device_paths);
319 }
320
321 // Handles the result of FormatDevice and calls |callback| or
322 // |error_callback|.
323 void OnFormatDevice(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35324 const FormatDeviceCallback& callback,
325 const ErrorCallback& error_callback,
[email protected]4ae73292011-11-15 05:20:18326 dbus::Response* response) {
327 if (!response) {
328 error_callback.Run();
329 return;
330 }
331 dbus::MessageReader reader(response);
332 bool success = false;
333 if (!reader.PopBool(&success)) {
334 LOG(ERROR) << "Invalid response: " << response->ToString();
335 error_callback.Run();
336 return;
337 }
338 callback.Run(device_path, success);
339 }
340
341 // Handles the result of GetDeviceProperties and calls |callback| or
342 // |error_callback|.
343 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35344 const GetDevicePropertiesCallback& callback,
345 const ErrorCallback& error_callback,
[email protected]4ae73292011-11-15 05:20:18346 dbus::Response* response) {
347 if (!response) {
348 error_callback.Run();
349 return;
350 }
351 DiskInfo disk(device_path, response);
352 callback.Run(disk);
353 }
354
355 // Handles mount event signals and calls |handler|.
356 void OnMountEvent(MountEventType event_type,
357 MountEventHandler handler,
358 dbus::Signal* signal) {
359 dbus::MessageReader reader(signal);
360 std::string device;
361 if (!reader.PopString(&device)) {
362 LOG(ERROR) << "Invalid signal: " << signal->ToString();
363 return;
364 }
365 handler.Run(event_type, device);
366 }
367
368 // Handles MountCompleted signal and calls |handler|.
369 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
370 dbus::MessageReader reader(signal);
371 unsigned int error_code = 0;
372 std::string source_path;
373 unsigned int mount_type = 0;
374 std::string mount_path;
375 if (!reader.PopUint32(&error_code) ||
376 !reader.PopString(&source_path) ||
377 !reader.PopUint32(&mount_type) ||
378 !reader.PopString(&mount_path)) {
379 LOG(ERROR) << "Invalid signal: " << signal->ToString();
380 return;
381 }
382 handler.Run(static_cast<MountError>(error_code), source_path,
383 static_cast<MountType>(mount_type), mount_path);
384 }
385
386 // Handles the result of signal connection setup.
387 void OnSignalConnected(const std::string& interface,
388 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43389 bool succeeded) {
390 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18391 signal << " failed.";
392 }
393
394 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16395
396 // Note: This should remain the last member so it'll be destroyed and
397 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18398 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
399
400 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
401};
402
403// A stub implementaion of CrosDisksClient.
404class CrosDisksClientStubImpl : public CrosDisksClient {
405 public:
[email protected]593cf3b2013-03-05 04:16:52406 CrosDisksClientStubImpl()
[email protected]637c17b82013-04-26 08:13:10407 : weak_ptr_factory_(this) {}
[email protected]593cf3b2013-03-05 04:16:52408
[email protected]4ae73292011-11-15 05:20:18409 virtual ~CrosDisksClientStubImpl() {}
410
[email protected]593cf3b2013-03-05 04:16:52411 // CrosDisksClient overrides:
[email protected]4ae73292011-11-15 05:20:18412 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48413 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33414 const std::string& mount_label,
[email protected]4ae73292011-11-15 05:20:18415 MountType type,
[email protected]4a404e52012-04-11 02:25:35416 const MountCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52417 const ErrorCallback& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52418 // This stub implementation only accepts archive mount requests.
419 if (type != MOUNT_TYPE_ARCHIVE) {
420 FinishMount(MOUNT_ERROR_INTERNAL, source_path, type, std::string(),
421 callback);
422 return;
423 }
424
425 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
426 base::FilePath::FromUTF8Unsafe(mount_label));
427
[email protected]be0ed642013-03-07 06:39:32428 // Already mounted path.
429 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
430 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
431 std::string(), callback);
432 return;
433 }
434
[email protected]593cf3b2013-03-05 04:16:52435 // Perform fake mount.
436 base::PostTaskAndReplyWithResult(
[email protected]144b6c42013-06-14 07:30:38437 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
[email protected]593cf3b2013-03-05 04:16:52438 FROM_HERE,
[email protected]144b6c42013-06-14 07:30:38439 base::Bind(&PerformFakeMount, source_path, mounted_path),
[email protected]593cf3b2013-03-05 04:16:52440 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
441 weak_ptr_factory_.GetWeakPtr(),
442 source_path,
443 type,
444 callback,
445 mounted_path));
446 }
447
[email protected]4ae73292011-11-15 05:20:18448 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49449 UnmountOptions options,
[email protected]4a404e52012-04-11 02:25:35450 const UnmountCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52451 const UnmountCallback& error_callback) OVERRIDE {
452 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32453 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]593cf3b2013-03-05 04:16:52454 base::MessageLoopProxy::current()->PostTask(
455 FROM_HERE, base::Bind(error_callback, device_path));
456 return;
457 }
458
[email protected]be0ed642013-03-07 06:39:32459 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52460
461 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32462 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52463 FROM_HERE,
464 base::Bind(base::IgnoreResult(&file_util::Delete),
[email protected]be0ed642013-03-07 06:39:32465 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52466 true /* recursive */),
[email protected]be0ed642013-03-07 06:39:32467 base::Bind(callback, device_path),
[email protected]593cf3b2013-03-05 04:16:52468 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52469 }
470
[email protected]4ae73292011-11-15 05:20:18471 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35472 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52473 const ErrorCallback& error_callback) OVERRIDE {
474 std::vector<std::string> device_paths;
475 base::MessageLoopProxy::current()->PostTask(
476 FROM_HERE, base::Bind(callback, device_paths));
477 }
478
[email protected]4ae73292011-11-15 05:20:18479 virtual void FormatDevice(const std::string& device_path,
480 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35481 const FormatDeviceCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52482 const ErrorCallback& error_callback) OVERRIDE {
483 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
484 }
485
[email protected]4a404e52012-04-11 02:25:35486 virtual void GetDeviceProperties(
487 const std::string& device_path,
488 const GetDevicePropertiesCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52489 const ErrorCallback& error_callback) OVERRIDE {
490 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
491 }
492
[email protected]4ae73292011-11-15 05:20:18493 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35494 const MountEventHandler& mount_event_handler,
[email protected]593cf3b2013-03-05 04:16:52495 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
496 mount_event_handler_ = mount_event_handler;
497 mount_completed_handler_ = mount_completed_handler;
498 }
[email protected]4ae73292011-11-15 05:20:18499
500 private:
[email protected]593cf3b2013-03-05 04:16:52501 // Performs file actions for Mount().
502 static MountError PerformFakeMount(const std::string& source_path,
503 const base::FilePath& mounted_path) {
504 // Check the source path exists.
505 if (!file_util::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
506 DLOG(ERROR) << "Source does not exist at " << source_path;
507 return MOUNT_ERROR_INVALID_PATH;
508 }
509
510 // Just create an empty directory and shows it as the mounted directory.
511 if (!file_util::CreateDirectory(mounted_path)) {
512 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
513 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
514 }
515
516 // Put a dummy file.
517 const base::FilePath dummy_file_path =
518 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
519 const std::string dummy_file_content = "This is a dummy file.";
520 const int write_result = file_util::WriteFile(
521 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
522 if (write_result != static_cast<int>(dummy_file_content.size())) {
523 DLOG(ERROR) << "Failed to put a dummy file at "
524 << dummy_file_path.value();
525 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
526 }
527
528 return MOUNT_ERROR_NONE;
529 }
530
531 // Part of Mount() implementation.
532 void ContinueMount(const std::string& source_path,
533 MountType type,
534 const MountCallback& callback,
535 const base::FilePath& mounted_path,
536 MountError mount_error) {
537 if (mount_error != MOUNT_ERROR_NONE) {
538 FinishMount(mount_error, source_path, type, std::string(), callback);
539 return;
540 }
[email protected]be0ed642013-03-07 06:39:32541 mounted_to_source_path_map_[mounted_path.value()] = source_path;
[email protected]593cf3b2013-03-05 04:16:52542 FinishMount(MOUNT_ERROR_NONE, source_path, type,
543 mounted_path.AsUTF8Unsafe(), callback);
544 }
545
546 // Runs |callback| and sends MountCompleted signal.
547 // Part of Mount() implementation.
548 void FinishMount(MountError error,
549 const std::string& source_path,
550 MountType type,
551 const std::string& mounted_path,
552 const MountCallback& callback) {
553 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
554 if (!mount_completed_handler_.is_null()) {
555 base::MessageLoopProxy::current()->PostTask(
556 FROM_HERE,
557 base::Bind(mount_completed_handler_,
558 error, source_path, type, mounted_path));
559 }
560 }
561
[email protected]be0ed642013-03-07 06:39:32562 // Mounted path to source path map.
563 std::map<std::string, std::string> mounted_to_source_path_map_;
[email protected]593cf3b2013-03-05 04:16:52564
565 MountEventHandler mount_event_handler_;
566 MountCompletedHandler mount_completed_handler_;
567
568 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
569
[email protected]4ae73292011-11-15 05:20:18570 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
571};
572
[email protected]85b95a2012012-08-07 18:57:27573} // namespace
[email protected]4ae73292011-11-15 05:20:18574
575////////////////////////////////////////////////////////////////////////////////
576// DiskInfo
577
578DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
579 : device_path_(device_path),
580 is_drive_(false),
581 has_media_(false),
582 on_boot_device_(false),
[email protected]2321d282012-01-31 23:06:59583 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18584 total_size_in_bytes_(0),
585 is_read_only_(false),
586 is_hidden_(true) {
587 InitializeFromResponse(response);
588}
589
590DiskInfo::~DiskInfo() {
591}
592
[email protected]85b95a2012012-08-07 18:57:27593// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18594// Below is an example of |response|'s raw message (long string is ellipsized).
595//
596//
597// message_type: MESSAGE_METHOD_RETURN
598// destination: :1.8
599// sender: :1.16
600// signature: a{sv}
601// serial: 96
602// reply_serial: 267
603//
604// array [
605// dict entry {
606// string "DeviceFile"
607// variant string "/dev/sdb"
608// }
609// dict entry {
610// string "DeviceIsDrive"
611// variant bool true
612// }
613// dict entry {
614// string "DeviceIsMediaAvailable"
615// variant bool true
616// }
617// dict entry {
618// string "DeviceIsMounted"
619// variant bool false
620// }
621// dict entry {
622// string "DeviceIsOnBootDevice"
623// variant bool false
624// }
625// dict entry {
[email protected]4ae73292011-11-15 05:20:18626// string "DeviceIsReadOnly"
627// variant bool false
628// }
629// dict entry {
630// string "DeviceIsVirtual"
631// variant bool false
632// }
633// dict entry {
634// string "DeviceMediaType"
635// variant uint32 1
636// }
637// dict entry {
638// string "DeviceMountPaths"
639// variant array [
640// ]
641// }
642// dict entry {
643// string "DevicePresentationHide"
644// variant bool true
645// }
646// dict entry {
647// string "DeviceSize"
648// variant uint64 7998537728
649// }
650// dict entry {
651// string "DriveIsRotational"
652// variant bool false
653// }
654// dict entry {
[email protected]202e9fee2012-09-13 20:21:29655// string "VendorId"
656// variant string "18d1"
657// }
658// dict entry {
659// string "VendorName"
660// variant string "Google Inc."
661// }
662// dict entry {
663// string "ProductId"
664// variant string "4e11"
665// }
666// dict entry {
667// string "ProductName"
668// variant string "Nexus One"
669// }
670// dict entry {
[email protected]4ae73292011-11-15 05:20:18671// string "DriveModel"
672// variant string "TransMemory"
673// }
674// dict entry {
675// string "IdLabel"
676// variant string ""
677// }
678// dict entry {
679// string "IdUuid"
680// variant string ""
681// }
682// dict entry {
683// string "NativePath"
684// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
685// }
686// ]
687void DiskInfo::InitializeFromResponse(dbus::Response* response) {
688 dbus::MessageReader response_reader(response);
689 dbus::MessageReader array_reader(response);
690 if (!response_reader.PopArray(&array_reader)) {
691 LOG(ERROR) << "Invalid response: " << response->ToString();
692 return;
693 }
694 // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
[email protected]b307bceb2011-11-17 07:49:55695 typedef std::map<std::string, dbus::MessageReader*> PropertiesMap;
696 PropertiesMap properties;
697 STLValueDeleter<PropertiesMap> properties_value_deleter(&properties);
[email protected]4ae73292011-11-15 05:20:18698 while (array_reader.HasMoreData()) {
[email protected]4ae73292011-11-15 05:20:18699 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
[email protected]4ae73292011-11-15 05:20:18700 dbus::MessageReader dict_entry_reader(response);
701 std::string key;
702 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
703 !dict_entry_reader.PopString(&key) ||
704 !dict_entry_reader.PopVariant(value_reader)) {
705 LOG(ERROR) << "Invalid response: " << response->ToString();
706 return;
707 }
708 properties[key] = value_reader;
709 }
710 MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
711 MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
712 MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
713 MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
714 MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
715 &on_boot_device_);
716 MaybePopString(properties[cros_disks::kNativePath], &system_path_);
717 MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
[email protected]202e9fee2012-09-13 20:21:29718 MaybePopString(properties[cros_disks::kVendorId], &vendor_id_);
719 MaybePopString(properties[cros_disks::kVendorName], &vendor_name_);
720 MaybePopString(properties[cros_disks::kProductId], &product_id_);
721 MaybePopString(properties[cros_disks::kProductName], &product_name_);
[email protected]4ae73292011-11-15 05:20:18722 MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
723 MaybePopString(properties[cros_disks::kIdLabel], &label_);
[email protected]9c5620d32012-07-31 01:00:38724 MaybePopString(properties[cros_disks::kIdUuid], &uuid_);
[email protected]4ae73292011-11-15 05:20:18725 MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_);
726
[email protected]2321d282012-01-31 23:06:59727 uint32 media_type_uint32 = 0;
728 if (MaybePopUint32(properties[cros_disks::kDeviceMediaType],
729 &media_type_uint32)) {
730 device_type_ = DeviceMediaTypeToDeviceType(media_type_uint32);
731 }
732
[email protected]4ae73292011-11-15 05:20:18733 std::vector<std::string> mount_paths;
734 if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
735 &mount_paths) && !mount_paths.empty())
736 mount_path_ = mount_paths[0];
[email protected]4ae73292011-11-15 05:20:18737}
738
739////////////////////////////////////////////////////////////////////////////////
740// CrosDisksClient
741
742CrosDisksClient::CrosDisksClient() {}
743
744CrosDisksClient::~CrosDisksClient() {}
745
746// static
[email protected]e8db03d62012-03-31 04:08:38747CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type,
748 dbus::Bus* bus) {
749 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]4ae73292011-11-15 05:20:18750 return new CrosDisksClientImpl(bus);
[email protected]e8db03d62012-03-31 04:08:38751 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
752 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18753}
754
[email protected]a5a8b412013-03-04 15:03:11755// static
756base::FilePath CrosDisksClient::GetArchiveMountPoint() {
757 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
758 FILE_PATH_LITERAL("/media/archive") :
759 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
760}
761
762// static
763base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
764 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
765 FILE_PATH_LITERAL("/media/removable") :
766 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
767}
768
[email protected]4ae73292011-11-15 05:20:18769} // namespace chromeos