blob: 4c302c283b80b1ab003de1fdca7cebe4a201d9a5 [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"
14#include "base/message_loop_proxy.h"
[email protected]b307bceb2011-11-17 07:49:5515#include "base/stl_util.h"
[email protected]dcad8fc2012-04-30 23:31:3316#include "base/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()
407 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
408
[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(
437 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
438 FROM_HERE,
439 base::Bind(&PerformFakeMount,
440 source_path,
441 mounted_path),
442 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
443 weak_ptr_factory_.GetWeakPtr(),
444 source_path,
445 type,
446 callback,
447 mounted_path));
448 }
449
[email protected]4ae73292011-11-15 05:20:18450 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49451 UnmountOptions options,
[email protected]4a404e52012-04-11 02:25:35452 const UnmountCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52453 const UnmountCallback& error_callback) OVERRIDE {
454 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32455 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]593cf3b2013-03-05 04:16:52456 base::MessageLoopProxy::current()->PostTask(
457 FROM_HERE, base::Bind(error_callback, device_path));
458 return;
459 }
460
[email protected]be0ed642013-03-07 06:39:32461 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52462
463 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32464 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52465 FROM_HERE,
466 base::Bind(base::IgnoreResult(&file_util::Delete),
[email protected]be0ed642013-03-07 06:39:32467 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52468 true /* recursive */),
[email protected]be0ed642013-03-07 06:39:32469 base::Bind(callback, device_path),
[email protected]593cf3b2013-03-05 04:16:52470 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52471 }
472
[email protected]4ae73292011-11-15 05:20:18473 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35474 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52475 const ErrorCallback& error_callback) OVERRIDE {
476 std::vector<std::string> device_paths;
477 base::MessageLoopProxy::current()->PostTask(
478 FROM_HERE, base::Bind(callback, device_paths));
479 }
480
[email protected]4ae73292011-11-15 05:20:18481 virtual void FormatDevice(const std::string& device_path,
482 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35483 const FormatDeviceCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52484 const ErrorCallback& error_callback) OVERRIDE {
485 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
486 }
487
[email protected]4a404e52012-04-11 02:25:35488 virtual void GetDeviceProperties(
489 const std::string& device_path,
490 const GetDevicePropertiesCallback& callback,
[email protected]593cf3b2013-03-05 04:16:52491 const ErrorCallback& error_callback) OVERRIDE {
492 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
493 }
494
[email protected]4ae73292011-11-15 05:20:18495 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35496 const MountEventHandler& mount_event_handler,
[email protected]593cf3b2013-03-05 04:16:52497 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
498 mount_event_handler_ = mount_event_handler;
499 mount_completed_handler_ = mount_completed_handler;
500 }
[email protected]4ae73292011-11-15 05:20:18501
502 private:
[email protected]593cf3b2013-03-05 04:16:52503 // Performs file actions for Mount().
504 static MountError PerformFakeMount(const std::string& source_path,
505 const base::FilePath& mounted_path) {
506 // Check the source path exists.
507 if (!file_util::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
508 DLOG(ERROR) << "Source does not exist at " << source_path;
509 return MOUNT_ERROR_INVALID_PATH;
510 }
511
512 // Just create an empty directory and shows it as the mounted directory.
513 if (!file_util::CreateDirectory(mounted_path)) {
514 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
515 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
516 }
517
518 // Put a dummy file.
519 const base::FilePath dummy_file_path =
520 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
521 const std::string dummy_file_content = "This is a dummy file.";
522 const int write_result = file_util::WriteFile(
523 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
524 if (write_result != static_cast<int>(dummy_file_content.size())) {
525 DLOG(ERROR) << "Failed to put a dummy file at "
526 << dummy_file_path.value();
527 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
528 }
529
530 return MOUNT_ERROR_NONE;
531 }
532
533 // Part of Mount() implementation.
534 void ContinueMount(const std::string& source_path,
535 MountType type,
536 const MountCallback& callback,
537 const base::FilePath& mounted_path,
538 MountError mount_error) {
539 if (mount_error != MOUNT_ERROR_NONE) {
540 FinishMount(mount_error, source_path, type, std::string(), callback);
541 return;
542 }
[email protected]be0ed642013-03-07 06:39:32543 mounted_to_source_path_map_[mounted_path.value()] = source_path;
[email protected]593cf3b2013-03-05 04:16:52544 FinishMount(MOUNT_ERROR_NONE, source_path, type,
545 mounted_path.AsUTF8Unsafe(), callback);
546 }
547
548 // Runs |callback| and sends MountCompleted signal.
549 // Part of Mount() implementation.
550 void FinishMount(MountError error,
551 const std::string& source_path,
552 MountType type,
553 const std::string& mounted_path,
554 const MountCallback& callback) {
555 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
556 if (!mount_completed_handler_.is_null()) {
557 base::MessageLoopProxy::current()->PostTask(
558 FROM_HERE,
559 base::Bind(mount_completed_handler_,
560 error, source_path, type, mounted_path));
561 }
562 }
563
[email protected]be0ed642013-03-07 06:39:32564 // Mounted path to source path map.
565 std::map<std::string, std::string> mounted_to_source_path_map_;
[email protected]593cf3b2013-03-05 04:16:52566
567 MountEventHandler mount_event_handler_;
568 MountCompletedHandler mount_completed_handler_;
569
570 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
571
[email protected]4ae73292011-11-15 05:20:18572 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
573};
574
[email protected]85b95a2012012-08-07 18:57:27575} // namespace
[email protected]4ae73292011-11-15 05:20:18576
577////////////////////////////////////////////////////////////////////////////////
578// DiskInfo
579
580DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
581 : device_path_(device_path),
582 is_drive_(false),
583 has_media_(false),
584 on_boot_device_(false),
[email protected]2321d282012-01-31 23:06:59585 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18586 total_size_in_bytes_(0),
587 is_read_only_(false),
588 is_hidden_(true) {
589 InitializeFromResponse(response);
590}
591
592DiskInfo::~DiskInfo() {
593}
594
[email protected]85b95a2012012-08-07 18:57:27595// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18596// Below is an example of |response|'s raw message (long string is ellipsized).
597//
598//
599// message_type: MESSAGE_METHOD_RETURN
600// destination: :1.8
601// sender: :1.16
602// signature: a{sv}
603// serial: 96
604// reply_serial: 267
605//
606// array [
607// dict entry {
608// string "DeviceFile"
609// variant string "/dev/sdb"
610// }
611// dict entry {
612// string "DeviceIsDrive"
613// variant bool true
614// }
615// dict entry {
616// string "DeviceIsMediaAvailable"
617// variant bool true
618// }
619// dict entry {
620// string "DeviceIsMounted"
621// variant bool false
622// }
623// dict entry {
624// string "DeviceIsOnBootDevice"
625// variant bool false
626// }
627// dict entry {
[email protected]4ae73292011-11-15 05:20:18628// string "DeviceIsReadOnly"
629// variant bool false
630// }
631// dict entry {
632// string "DeviceIsVirtual"
633// variant bool false
634// }
635// dict entry {
636// string "DeviceMediaType"
637// variant uint32 1
638// }
639// dict entry {
640// string "DeviceMountPaths"
641// variant array [
642// ]
643// }
644// dict entry {
645// string "DevicePresentationHide"
646// variant bool true
647// }
648// dict entry {
649// string "DeviceSize"
650// variant uint64 7998537728
651// }
652// dict entry {
653// string "DriveIsRotational"
654// variant bool false
655// }
656// dict entry {
[email protected]202e9fee2012-09-13 20:21:29657// string "VendorId"
658// variant string "18d1"
659// }
660// dict entry {
661// string "VendorName"
662// variant string "Google Inc."
663// }
664// dict entry {
665// string "ProductId"
666// variant string "4e11"
667// }
668// dict entry {
669// string "ProductName"
670// variant string "Nexus One"
671// }
672// dict entry {
[email protected]4ae73292011-11-15 05:20:18673// string "DriveModel"
674// variant string "TransMemory"
675// }
676// dict entry {
677// string "IdLabel"
678// variant string ""
679// }
680// dict entry {
681// string "IdUuid"
682// variant string ""
683// }
684// dict entry {
685// string "NativePath"
686// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
687// }
688// ]
689void DiskInfo::InitializeFromResponse(dbus::Response* response) {
690 dbus::MessageReader response_reader(response);
691 dbus::MessageReader array_reader(response);
692 if (!response_reader.PopArray(&array_reader)) {
693 LOG(ERROR) << "Invalid response: " << response->ToString();
694 return;
695 }
696 // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
[email protected]b307bceb2011-11-17 07:49:55697 typedef std::map<std::string, dbus::MessageReader*> PropertiesMap;
698 PropertiesMap properties;
699 STLValueDeleter<PropertiesMap> properties_value_deleter(&properties);
[email protected]4ae73292011-11-15 05:20:18700 while (array_reader.HasMoreData()) {
[email protected]4ae73292011-11-15 05:20:18701 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
[email protected]4ae73292011-11-15 05:20:18702 dbus::MessageReader dict_entry_reader(response);
703 std::string key;
704 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
705 !dict_entry_reader.PopString(&key) ||
706 !dict_entry_reader.PopVariant(value_reader)) {
707 LOG(ERROR) << "Invalid response: " << response->ToString();
708 return;
709 }
710 properties[key] = value_reader;
711 }
712 MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
713 MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
714 MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
715 MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
716 MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
717 &on_boot_device_);
718 MaybePopString(properties[cros_disks::kNativePath], &system_path_);
719 MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
[email protected]202e9fee2012-09-13 20:21:29720 MaybePopString(properties[cros_disks::kVendorId], &vendor_id_);
721 MaybePopString(properties[cros_disks::kVendorName], &vendor_name_);
722 MaybePopString(properties[cros_disks::kProductId], &product_id_);
723 MaybePopString(properties[cros_disks::kProductName], &product_name_);
[email protected]4ae73292011-11-15 05:20:18724 MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
725 MaybePopString(properties[cros_disks::kIdLabel], &label_);
[email protected]9c5620d32012-07-31 01:00:38726 MaybePopString(properties[cros_disks::kIdUuid], &uuid_);
[email protected]4ae73292011-11-15 05:20:18727 MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_);
728
[email protected]2321d282012-01-31 23:06:59729 uint32 media_type_uint32 = 0;
730 if (MaybePopUint32(properties[cros_disks::kDeviceMediaType],
731 &media_type_uint32)) {
732 device_type_ = DeviceMediaTypeToDeviceType(media_type_uint32);
733 }
734
[email protected]4ae73292011-11-15 05:20:18735 std::vector<std::string> mount_paths;
736 if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
737 &mount_paths) && !mount_paths.empty())
738 mount_path_ = mount_paths[0];
[email protected]4ae73292011-11-15 05:20:18739}
740
741////////////////////////////////////////////////////////////////////////////////
742// CrosDisksClient
743
744CrosDisksClient::CrosDisksClient() {}
745
746CrosDisksClient::~CrosDisksClient() {}
747
748// static
[email protected]e8db03d62012-03-31 04:08:38749CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type,
750 dbus::Bus* bus) {
751 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]4ae73292011-11-15 05:20:18752 return new CrosDisksClientImpl(bus);
[email protected]e8db03d62012-03-31 04:08:38753 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
754 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18755}
756
[email protected]a5a8b412013-03-04 15:03:11757// static
758base::FilePath CrosDisksClient::GetArchiveMountPoint() {
759 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
760 FILE_PATH_LITERAL("/media/archive") :
761 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
762}
763
764// static
765base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
766 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
767 FILE_PATH_LITERAL("/media/removable") :
768 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
769}
770
[email protected]4ae73292011-11-15 05:20:18771} // namespace chromeos