blob: c48ceccc66cef7cfae664b3b9eafc7e6b1826f13 [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]5624a252013-07-04 03:17:53135 const base::Closure& callback,
136 const base::Closure& 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]ffdcc7a9c2013-07-02 06:59:39162 const base::Closure& callback,
163 const base::Closure& 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(),
[email protected]4ae73292011-11-15 05:20:18179 callback,
180 error_callback));
181 }
182
183 // CrosDisksClient override.
184 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35185 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53186 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18187 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
188 cros_disks::kEnumerateAutoMountableDevices);
189 proxy_->CallMethod(
190 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
191 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
192 weak_ptr_factory_.GetWeakPtr(),
193 callback,
194 error_callback));
195 }
196
197 // CrosDisksClient override.
198 virtual void FormatDevice(const std::string& device_path,
199 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35200 const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53201 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18202 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
203 cros_disks::kFormatDevice);
204 dbus::MessageWriter writer(&method_call);
205 writer.AppendString(device_path);
206 writer.AppendString(filesystem);
207 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
208 base::Bind(&CrosDisksClientImpl::OnFormatDevice,
209 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18210 callback,
211 error_callback));
212 }
213
214 // CrosDisksClient override.
[email protected]4a404e52012-04-11 02:25:35215 virtual void GetDeviceProperties(
216 const std::string& device_path,
217 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53218 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18219 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
220 cros_disks::kGetDeviceProperties);
221 dbus::MessageWriter writer(&method_call);
222 writer.AppendString(device_path);
223 proxy_->CallMethod(&method_call,
224 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
225 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
226 weak_ptr_factory_.GetWeakPtr(),
227 device_path,
228 callback,
229 error_callback));
230 }
231
232 // CrosDisksClient override.
233 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35234 const MountEventHandler& mount_event_handler,
235 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18236 static const SignalEventTuple kSignalEventTuples[] = {
[email protected]e3c1fc92012-11-15 00:56:46237 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
238 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
239 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
240 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
241 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
242 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
243 { cros_disks::kFormattingFinished, CROS_DISKS_FORMATTING_FINISHED },
[email protected]4ae73292011-11-15 05:20:18244 };
245 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
246
247 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
248 proxy_->ConnectToSignal(
249 cros_disks::kCrosDisksInterface,
250 kSignalEventTuples[i].signal_name,
251 base::Bind(&CrosDisksClientImpl::OnMountEvent,
252 weak_ptr_factory_.GetWeakPtr(),
253 kSignalEventTuples[i].event_type,
254 mount_event_handler),
255 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
256 weak_ptr_factory_.GetWeakPtr()));
257 }
258 proxy_->ConnectToSignal(
259 cros_disks::kCrosDisksInterface,
[email protected]b3e3f492011-11-18 18:46:00260 cros_disks::kMountCompleted,
[email protected]4ae73292011-11-15 05:20:18261 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
262 weak_ptr_factory_.GetWeakPtr(),
[email protected]85b95a2012012-08-07 18:57:27263 mount_completed_handler),
[email protected]4ae73292011-11-15 05:20:18264 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
265 weak_ptr_factory_.GetWeakPtr()));
266 }
267
268 private:
269 // A struct to contain a pair of signal name and mount event type.
270 // Used by SetUpConnections.
271 struct SignalEventTuple {
272 const char *signal_name;
273 MountEventType event_type;
274 };
275
276 // Handles the result of Mount and calls |callback| or |error_callback|.
[email protected]5624a252013-07-04 03:17:53277 void OnMount(const base::Closure& callback,
278 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18279 dbus::Response* response) {
280 if (!response) {
281 error_callback.Run();
282 return;
283 }
284 callback.Run();
285 }
286
287 // Handles the result of Unount and calls |callback| or |error_callback|.
[email protected]ffdcc7a9c2013-07-02 06:59:39288 void OnUnmount(const base::Closure& callback,
289 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18290 dbus::Response* response) {
291 if (!response) {
[email protected]ffdcc7a9c2013-07-02 06:59:39292 error_callback.Run();
[email protected]4ae73292011-11-15 05:20:18293 return;
294 }
[email protected]ffdcc7a9c2013-07-02 06:59:39295 callback.Run();
[email protected]4ae73292011-11-15 05:20:18296 }
297
298 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
299 // |error_callback|.
300 void OnEnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35301 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53302 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18303 dbus::Response* response) {
304 if (!response) {
305 error_callback.Run();
306 return;
307 }
308 dbus::MessageReader reader(response);
309 std::vector<std::string> device_paths;
310 if (!reader.PopArrayOfStrings(&device_paths)) {
311 LOG(ERROR) << "Invalid response: " << response->ToString();
312 error_callback.Run();
313 return;
314 }
315 callback.Run(device_paths);
316 }
317
318 // Handles the result of FormatDevice and calls |callback| or
319 // |error_callback|.
[email protected]15a2c282013-07-03 08:39:49320 void OnFormatDevice(const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53321 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18322 dbus::Response* response) {
323 if (!response) {
324 error_callback.Run();
325 return;
326 }
327 dbus::MessageReader reader(response);
328 bool success = false;
329 if (!reader.PopBool(&success)) {
330 LOG(ERROR) << "Invalid response: " << response->ToString();
331 error_callback.Run();
332 return;
333 }
[email protected]15a2c282013-07-03 08:39:49334 callback.Run(success);
[email protected]4ae73292011-11-15 05:20:18335 }
336
337 // Handles the result of GetDeviceProperties and calls |callback| or
338 // |error_callback|.
339 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35340 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53341 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18342 dbus::Response* response) {
343 if (!response) {
344 error_callback.Run();
345 return;
346 }
347 DiskInfo disk(device_path, response);
348 callback.Run(disk);
349 }
350
351 // Handles mount event signals and calls |handler|.
352 void OnMountEvent(MountEventType event_type,
353 MountEventHandler handler,
354 dbus::Signal* signal) {
355 dbus::MessageReader reader(signal);
356 std::string device;
357 if (!reader.PopString(&device)) {
358 LOG(ERROR) << "Invalid signal: " << signal->ToString();
359 return;
360 }
361 handler.Run(event_type, device);
362 }
363
364 // Handles MountCompleted signal and calls |handler|.
365 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
366 dbus::MessageReader reader(signal);
367 unsigned int error_code = 0;
368 std::string source_path;
369 unsigned int mount_type = 0;
370 std::string mount_path;
371 if (!reader.PopUint32(&error_code) ||
372 !reader.PopString(&source_path) ||
373 !reader.PopUint32(&mount_type) ||
374 !reader.PopString(&mount_path)) {
375 LOG(ERROR) << "Invalid signal: " << signal->ToString();
376 return;
377 }
378 handler.Run(static_cast<MountError>(error_code), source_path,
379 static_cast<MountType>(mount_type), mount_path);
380 }
381
382 // Handles the result of signal connection setup.
383 void OnSignalConnected(const std::string& interface,
384 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43385 bool succeeded) {
386 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18387 signal << " failed.";
388 }
389
390 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16391
392 // Note: This should remain the last member so it'll be destroyed and
393 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18394 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
395
396 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
397};
398
399// A stub implementaion of CrosDisksClient.
400class CrosDisksClientStubImpl : public CrosDisksClient {
401 public:
[email protected]593cf3b2013-03-05 04:16:52402 CrosDisksClientStubImpl()
[email protected]637c17b82013-04-26 08:13:10403 : weak_ptr_factory_(this) {}
[email protected]593cf3b2013-03-05 04:16:52404
[email protected]4ae73292011-11-15 05:20:18405 virtual ~CrosDisksClientStubImpl() {}
406
[email protected]593cf3b2013-03-05 04:16:52407 // CrosDisksClient overrides:
[email protected]4ae73292011-11-15 05:20:18408 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48409 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33410 const std::string& mount_label,
[email protected]4ae73292011-11-15 05:20:18411 MountType type,
[email protected]5624a252013-07-04 03:17:53412 const base::Closure& callback,
413 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52414 // This stub implementation only accepts archive mount requests.
415 if (type != MOUNT_TYPE_ARCHIVE) {
416 FinishMount(MOUNT_ERROR_INTERNAL, source_path, type, std::string(),
417 callback);
418 return;
419 }
420
421 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
422 base::FilePath::FromUTF8Unsafe(mount_label));
423
[email protected]be0ed642013-03-07 06:39:32424 // Already mounted path.
425 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
426 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
427 std::string(), callback);
428 return;
429 }
430
[email protected]593cf3b2013-03-05 04:16:52431 // Perform fake mount.
432 base::PostTaskAndReplyWithResult(
[email protected]144b6c42013-06-14 07:30:38433 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
[email protected]593cf3b2013-03-05 04:16:52434 FROM_HERE,
[email protected]144b6c42013-06-14 07:30:38435 base::Bind(&PerformFakeMount, source_path, mounted_path),
[email protected]593cf3b2013-03-05 04:16:52436 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
437 weak_ptr_factory_.GetWeakPtr(),
438 source_path,
439 type,
440 callback,
441 mounted_path));
442 }
443
[email protected]4ae73292011-11-15 05:20:18444 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49445 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39446 const base::Closure& callback,
447 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52448 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32449 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]ffdcc7a9c2013-07-02 06:59:39450 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
[email protected]593cf3b2013-03-05 04:16:52451 return;
452 }
453
[email protected]be0ed642013-03-07 06:39:32454 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52455
456 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32457 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52458 FROM_HERE,
[email protected]918efbf2013-07-01 19:41:02459 base::Bind(base::IgnoreResult(&base::Delete),
[email protected]be0ed642013-03-07 06:39:32460 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52461 true /* recursive */),
[email protected]ffdcc7a9c2013-07-02 06:59:39462 callback,
[email protected]593cf3b2013-03-05 04:16:52463 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52464 }
465
[email protected]4ae73292011-11-15 05:20:18466 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35467 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53468 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52469 std::vector<std::string> device_paths;
470 base::MessageLoopProxy::current()->PostTask(
471 FROM_HERE, base::Bind(callback, device_paths));
472 }
473
[email protected]4ae73292011-11-15 05:20:18474 virtual void FormatDevice(const std::string& device_path,
475 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35476 const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53477 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52478 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
479 }
480
[email protected]4a404e52012-04-11 02:25:35481 virtual void GetDeviceProperties(
482 const std::string& device_path,
483 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53484 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52485 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
486 }
487
[email protected]4ae73292011-11-15 05:20:18488 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35489 const MountEventHandler& mount_event_handler,
[email protected]593cf3b2013-03-05 04:16:52490 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
491 mount_event_handler_ = mount_event_handler;
492 mount_completed_handler_ = mount_completed_handler;
493 }
[email protected]4ae73292011-11-15 05:20:18494
495 private:
[email protected]593cf3b2013-03-05 04:16:52496 // Performs file actions for Mount().
497 static MountError PerformFakeMount(const std::string& source_path,
498 const base::FilePath& mounted_path) {
499 // Check the source path exists.
500 if (!file_util::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
501 DLOG(ERROR) << "Source does not exist at " << source_path;
502 return MOUNT_ERROR_INVALID_PATH;
503 }
504
505 // Just create an empty directory and shows it as the mounted directory.
506 if (!file_util::CreateDirectory(mounted_path)) {
507 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
508 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
509 }
510
511 // Put a dummy file.
512 const base::FilePath dummy_file_path =
513 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
514 const std::string dummy_file_content = "This is a dummy file.";
515 const int write_result = file_util::WriteFile(
516 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
517 if (write_result != static_cast<int>(dummy_file_content.size())) {
518 DLOG(ERROR) << "Failed to put a dummy file at "
519 << dummy_file_path.value();
520 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
521 }
522
523 return MOUNT_ERROR_NONE;
524 }
525
526 // Part of Mount() implementation.
527 void ContinueMount(const std::string& source_path,
528 MountType type,
[email protected]5624a252013-07-04 03:17:53529 const base::Closure& callback,
[email protected]593cf3b2013-03-05 04:16:52530 const base::FilePath& mounted_path,
531 MountError mount_error) {
532 if (mount_error != MOUNT_ERROR_NONE) {
533 FinishMount(mount_error, source_path, type, std::string(), callback);
534 return;
535 }
[email protected]be0ed642013-03-07 06:39:32536 mounted_to_source_path_map_[mounted_path.value()] = source_path;
[email protected]593cf3b2013-03-05 04:16:52537 FinishMount(MOUNT_ERROR_NONE, source_path, type,
538 mounted_path.AsUTF8Unsafe(), callback);
539 }
540
541 // Runs |callback| and sends MountCompleted signal.
542 // Part of Mount() implementation.
543 void FinishMount(MountError error,
544 const std::string& source_path,
545 MountType type,
546 const std::string& mounted_path,
[email protected]5624a252013-07-04 03:17:53547 const base::Closure& callback) {
[email protected]593cf3b2013-03-05 04:16:52548 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
549 if (!mount_completed_handler_.is_null()) {
550 base::MessageLoopProxy::current()->PostTask(
551 FROM_HERE,
552 base::Bind(mount_completed_handler_,
553 error, source_path, type, mounted_path));
554 }
555 }
556
[email protected]be0ed642013-03-07 06:39:32557 // Mounted path to source path map.
558 std::map<std::string, std::string> mounted_to_source_path_map_;
[email protected]593cf3b2013-03-05 04:16:52559
560 MountEventHandler mount_event_handler_;
561 MountCompletedHandler mount_completed_handler_;
562
563 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
564
[email protected]4ae73292011-11-15 05:20:18565 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
566};
567
[email protected]85b95a2012012-08-07 18:57:27568} // namespace
[email protected]4ae73292011-11-15 05:20:18569
570////////////////////////////////////////////////////////////////////////////////
571// DiskInfo
572
573DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
574 : device_path_(device_path),
575 is_drive_(false),
576 has_media_(false),
577 on_boot_device_(false),
[email protected]2321d282012-01-31 23:06:59578 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18579 total_size_in_bytes_(0),
580 is_read_only_(false),
581 is_hidden_(true) {
582 InitializeFromResponse(response);
583}
584
585DiskInfo::~DiskInfo() {
586}
587
[email protected]85b95a2012012-08-07 18:57:27588// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18589// Below is an example of |response|'s raw message (long string is ellipsized).
590//
591//
592// message_type: MESSAGE_METHOD_RETURN
593// destination: :1.8
594// sender: :1.16
595// signature: a{sv}
596// serial: 96
597// reply_serial: 267
598//
599// array [
600// dict entry {
601// string "DeviceFile"
602// variant string "/dev/sdb"
603// }
604// dict entry {
605// string "DeviceIsDrive"
606// variant bool true
607// }
608// dict entry {
609// string "DeviceIsMediaAvailable"
610// variant bool true
611// }
612// dict entry {
613// string "DeviceIsMounted"
614// variant bool false
615// }
616// dict entry {
617// string "DeviceIsOnBootDevice"
618// variant bool false
619// }
620// dict entry {
[email protected]4ae73292011-11-15 05:20:18621// string "DeviceIsReadOnly"
622// variant bool false
623// }
624// dict entry {
625// string "DeviceIsVirtual"
626// variant bool false
627// }
628// dict entry {
629// string "DeviceMediaType"
630// variant uint32 1
631// }
632// dict entry {
633// string "DeviceMountPaths"
634// variant array [
635// ]
636// }
637// dict entry {
638// string "DevicePresentationHide"
639// variant bool true
640// }
641// dict entry {
642// string "DeviceSize"
643// variant uint64 7998537728
644// }
645// dict entry {
646// string "DriveIsRotational"
647// variant bool false
648// }
649// dict entry {
[email protected]202e9fee2012-09-13 20:21:29650// string "VendorId"
651// variant string "18d1"
652// }
653// dict entry {
654// string "VendorName"
655// variant string "Google Inc."
656// }
657// dict entry {
658// string "ProductId"
659// variant string "4e11"
660// }
661// dict entry {
662// string "ProductName"
663// variant string "Nexus One"
664// }
665// dict entry {
[email protected]4ae73292011-11-15 05:20:18666// string "DriveModel"
667// variant string "TransMemory"
668// }
669// dict entry {
670// string "IdLabel"
671// variant string ""
672// }
673// dict entry {
674// string "IdUuid"
675// variant string ""
676// }
677// dict entry {
678// string "NativePath"
679// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
680// }
681// ]
682void DiskInfo::InitializeFromResponse(dbus::Response* response) {
683 dbus::MessageReader response_reader(response);
684 dbus::MessageReader array_reader(response);
685 if (!response_reader.PopArray(&array_reader)) {
686 LOG(ERROR) << "Invalid response: " << response->ToString();
687 return;
688 }
689 // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
[email protected]b307bceb2011-11-17 07:49:55690 typedef std::map<std::string, dbus::MessageReader*> PropertiesMap;
691 PropertiesMap properties;
692 STLValueDeleter<PropertiesMap> properties_value_deleter(&properties);
[email protected]4ae73292011-11-15 05:20:18693 while (array_reader.HasMoreData()) {
[email protected]4ae73292011-11-15 05:20:18694 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
[email protected]4ae73292011-11-15 05:20:18695 dbus::MessageReader dict_entry_reader(response);
696 std::string key;
697 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
698 !dict_entry_reader.PopString(&key) ||
699 !dict_entry_reader.PopVariant(value_reader)) {
700 LOG(ERROR) << "Invalid response: " << response->ToString();
701 return;
702 }
703 properties[key] = value_reader;
704 }
705 MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
706 MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
707 MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
708 MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
709 MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
710 &on_boot_device_);
711 MaybePopString(properties[cros_disks::kNativePath], &system_path_);
712 MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
[email protected]202e9fee2012-09-13 20:21:29713 MaybePopString(properties[cros_disks::kVendorId], &vendor_id_);
714 MaybePopString(properties[cros_disks::kVendorName], &vendor_name_);
715 MaybePopString(properties[cros_disks::kProductId], &product_id_);
716 MaybePopString(properties[cros_disks::kProductName], &product_name_);
[email protected]4ae73292011-11-15 05:20:18717 MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
718 MaybePopString(properties[cros_disks::kIdLabel], &label_);
[email protected]9c5620d32012-07-31 01:00:38719 MaybePopString(properties[cros_disks::kIdUuid], &uuid_);
[email protected]4ae73292011-11-15 05:20:18720 MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_);
721
[email protected]2321d282012-01-31 23:06:59722 uint32 media_type_uint32 = 0;
723 if (MaybePopUint32(properties[cros_disks::kDeviceMediaType],
724 &media_type_uint32)) {
725 device_type_ = DeviceMediaTypeToDeviceType(media_type_uint32);
726 }
727
[email protected]4ae73292011-11-15 05:20:18728 std::vector<std::string> mount_paths;
729 if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
730 &mount_paths) && !mount_paths.empty())
731 mount_path_ = mount_paths[0];
[email protected]4ae73292011-11-15 05:20:18732}
733
734////////////////////////////////////////////////////////////////////////////////
735// CrosDisksClient
736
737CrosDisksClient::CrosDisksClient() {}
738
739CrosDisksClient::~CrosDisksClient() {}
740
741// static
[email protected]e8db03d62012-03-31 04:08:38742CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type,
743 dbus::Bus* bus) {
744 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]4ae73292011-11-15 05:20:18745 return new CrosDisksClientImpl(bus);
[email protected]e8db03d62012-03-31 04:08:38746 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
747 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18748}
749
[email protected]a5a8b412013-03-04 15:03:11750// static
751base::FilePath CrosDisksClient::GetArchiveMountPoint() {
752 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
753 FILE_PATH_LITERAL("/media/archive") :
754 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
755}
756
757// static
758base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
759 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
760 FILE_PATH_LITERAL("/media/removable") :
761 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
762}
763
[email protected]4ae73292011-11-15 05:20:18764} // namespace chromeos