blob: cca2b17e7c720b7054c650f9d273a61d2647e9d5 [file] [log] [blame]
[email protected]2321d282012-01-31 23:06:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]4ae73292011-11-15 05:20:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]64e199252012-04-06 01:54:365#include "chromeos/dbus/cros_disks_client.h"
[email protected]4ae73292011-11-15 05:20:186
[email protected]85b95a2012012-08-07 18:57:277#include <map>
8
[email protected]4ae73292011-11-15 05:20:189#include "base/bind.h"
[email protected]593cf3b2013-03-05 04:16:5210#include "base/file_util.h"
[email protected]a5a8b412013-03-04 15:03:1111#include "base/files/file_path.h"
[email protected]593cf3b2013-03-05 04:16:5212#include "base/location.h"
[email protected]7ccb7072013-06-10 20:56:2813#include "base/message_loop/message_loop_proxy.h"
[email protected]b307bceb2011-11-17 07:49:5514#include "base/stl_util.h"
[email protected]afa339d72013-06-11 06:32:5115#include "base/strings/stringprintf.h"
[email protected]49c4cf852013-09-27 19:28:2416#include "base/sys_info.h"
[email protected]593cf3b2013-03-05 04:16:5217#include "base/task_runner_util.h"
18#include "base/threading/worker_pool.h"
[email protected]81836aed2013-07-09 23:41:1219#include "base/values.h"
[email protected]4ae73292011-11-15 05:20:1820#include "dbus/bus.h"
21#include "dbus/message.h"
[email protected]216ed0b2012-02-14 21:29:0622#include "dbus/object_path.h"
[email protected]4ae73292011-11-15 05:20:1823#include "dbus/object_proxy.h"
[email protected]81836aed2013-07-09 23:41:1224#include "dbus/values_util.h"
[email protected]4ae73292011-11-15 05:20:1825#include "third_party/cros_system_api/dbus/service_constants.h"
26
27namespace chromeos {
28
29namespace {
30
31const char* kDefaultMountOptions[] = {
32 "rw",
33 "nodev",
34 "noexec",
35 "nosuid",
[email protected]4ae73292011-11-15 05:20:1836};
37
38const char* kDefaultUnmountOptions[] = {
39 "force",
40};
41
[email protected]10795ae2012-10-10 07:33:4942const char kLazyUnmountOption[] = "lazy";
43
[email protected]dcad8fc2012-04-30 23:31:3344const char kMountLabelOption[] = "mountlabel";
45
[email protected]2321d282012-01-31 23:06:5946// Checks if retrieved media type is in boundaries of DeviceMediaType.
47bool IsValidMediaType(uint32 type) {
48 return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
49}
50
[email protected]2321d282012-01-31 23:06:5951// Translates enum used in cros-disks to enum used in Chrome.
52// Note that we could just do static_cast, but this is less sensitive to
53// changes in cros-disks.
54DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) {
55 if (!IsValidMediaType(media_type_uint32))
56 return DEVICE_TYPE_UNKNOWN;
57
58 cros_disks::DeviceMediaType media_type =
59 cros_disks::DeviceMediaType(media_type_uint32);
60
61 switch (media_type) {
62 case(cros_disks::DEVICE_MEDIA_UNKNOWN):
63 return DEVICE_TYPE_UNKNOWN;
64 case(cros_disks::DEVICE_MEDIA_USB):
65 return DEVICE_TYPE_USB;
66 case(cros_disks::DEVICE_MEDIA_SD):
67 return DEVICE_TYPE_SD;
68 case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
69 return DEVICE_TYPE_OPTICAL_DISC;
70 case(cros_disks::DEVICE_MEDIA_MOBILE):
71 return DEVICE_TYPE_MOBILE;
[email protected]f4ae40ac2012-05-04 21:57:0072 case(cros_disks::DEVICE_MEDIA_DVD):
73 return DEVICE_TYPE_DVD;
[email protected]2321d282012-01-31 23:06:5974 default:
75 return DEVICE_TYPE_UNKNOWN;
76 }
[email protected]4ae73292011-11-15 05:20:1877}
78
[email protected]4ae73292011-11-15 05:20:1879// The CrosDisksClient implementation.
80class CrosDisksClientImpl : public CrosDisksClient {
81 public:
[email protected]c5fd5362013-08-27 12:23:0482 CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
[email protected]4ae73292011-11-15 05:20:1883
84 // CrosDisksClient override.
85 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:4886 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:3387 const std::string& mount_label,
[email protected]5624a252013-07-04 03:17:5388 const base::Closure& callback,
89 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:1890 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
91 cros_disks::kMount);
92 dbus::MessageWriter writer(&method_call);
93 writer.AppendString(source_path);
[email protected]b9f22d12012-04-25 21:46:4894 writer.AppendString(source_format);
[email protected]4ae73292011-11-15 05:20:1895 std::vector<std::string> mount_options(kDefaultMountOptions,
96 kDefaultMountOptions +
97 arraysize(kDefaultMountOptions));
[email protected]dcad8fc2012-04-30 23:31:3398 if (!mount_label.empty()) {
99 std::string mount_label_option = base::StringPrintf("%s=%s",
100 kMountLabelOption,
101 mount_label.c_str());
102 mount_options.push_back(mount_label_option);
103 }
[email protected]4ae73292011-11-15 05:20:18104 writer.AppendArrayOfStrings(mount_options);
105 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
106 base::Bind(&CrosDisksClientImpl::OnMount,
107 weak_ptr_factory_.GetWeakPtr(),
108 callback,
109 error_callback));
110 }
111
112 // CrosDisksClient override.
113 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49114 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39115 const base::Closure& callback,
116 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18117 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
118 cros_disks::kUnmount);
119 dbus::MessageWriter writer(&method_call);
120 writer.AppendString(device_path);
[email protected]10795ae2012-10-10 07:33:49121
122 std::vector<std::string> unmount_options(
123 kDefaultUnmountOptions,
124 kDefaultUnmountOptions + arraysize(kDefaultUnmountOptions));
125 if (options == UNMOUNT_OPTIONS_LAZY)
126 unmount_options.push_back(kLazyUnmountOption);
127
[email protected]4ae73292011-11-15 05:20:18128 writer.AppendArrayOfStrings(unmount_options);
129 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
130 base::Bind(&CrosDisksClientImpl::OnUnmount,
131 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18132 callback,
133 error_callback));
134 }
135
136 // CrosDisksClient override.
137 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35138 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53139 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18140 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
141 cros_disks::kEnumerateAutoMountableDevices);
142 proxy_->CallMethod(
143 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
144 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
145 weak_ptr_factory_.GetWeakPtr(),
146 callback,
147 error_callback));
148 }
149
150 // CrosDisksClient override.
[email protected]f026c0f2014-05-06 21:52:35151 virtual void Format(const std::string& device_path,
152 const std::string& filesystem,
153 const base::Closure& callback,
154 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18155 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
[email protected]f026c0f2014-05-06 21:52:35156 cros_disks::kFormat);
[email protected]4ae73292011-11-15 05:20:18157 dbus::MessageWriter writer(&method_call);
158 writer.AppendString(device_path);
159 writer.AppendString(filesystem);
[email protected]f026c0f2014-05-06 21:52:35160 // No format option is currently specified, but we can later use this
161 // argument to specify options for the format operation.
162 std::vector<std::string> format_options;
163 writer.AppendArrayOfStrings(format_options);
[email protected]4ae73292011-11-15 05:20:18164 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
[email protected]f026c0f2014-05-06 21:52:35165 base::Bind(&CrosDisksClientImpl::OnFormat,
[email protected]4ae73292011-11-15 05:20:18166 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18167 callback,
168 error_callback));
169 }
170
171 // CrosDisksClient override.
[email protected]4a404e52012-04-11 02:25:35172 virtual void GetDeviceProperties(
173 const std::string& device_path,
174 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53175 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18176 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
177 cros_disks::kGetDeviceProperties);
178 dbus::MessageWriter writer(&method_call);
179 writer.AppendString(device_path);
180 proxy_->CallMethod(&method_call,
181 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
182 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
183 weak_ptr_factory_.GetWeakPtr(),
184 device_path,
185 callback,
186 error_callback));
187 }
188
189 // CrosDisksClient override.
[email protected]a0278d52014-05-06 03:36:15190 virtual void SetMountEventHandler(
191 const MountEventHandler& mount_event_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18192 static const SignalEventTuple kSignalEventTuples[] = {
[email protected]e3c1fc92012-11-15 00:56:46193 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
194 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
195 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
196 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
197 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
198 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
[email protected]4ae73292011-11-15 05:20:18199 };
200 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
201
202 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
203 proxy_->ConnectToSignal(
204 cros_disks::kCrosDisksInterface,
205 kSignalEventTuples[i].signal_name,
206 base::Bind(&CrosDisksClientImpl::OnMountEvent,
207 weak_ptr_factory_.GetWeakPtr(),
208 kSignalEventTuples[i].event_type,
209 mount_event_handler),
210 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
211 weak_ptr_factory_.GetWeakPtr()));
212 }
[email protected]a0278d52014-05-06 03:36:15213 }
214
215 // CrosDisksClient override.
216 virtual void SetMountCompletedHandler(
217 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18218 proxy_->ConnectToSignal(
219 cros_disks::kCrosDisksInterface,
[email protected]b3e3f492011-11-18 18:46:00220 cros_disks::kMountCompleted,
[email protected]4ae73292011-11-15 05:20:18221 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
222 weak_ptr_factory_.GetWeakPtr(),
[email protected]85b95a2012012-08-07 18:57:27223 mount_completed_handler),
[email protected]4ae73292011-11-15 05:20:18224 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
225 weak_ptr_factory_.GetWeakPtr()));
226 }
227
[email protected]a0278d52014-05-06 03:36:15228 // CrosDisksClient override.
229 virtual void SetFormatCompletedHandler(
230 const FormatCompletedHandler& format_completed_handler) OVERRIDE {
231 proxy_->ConnectToSignal(
232 cros_disks::kCrosDisksInterface,
233 cros_disks::kFormatCompleted,
234 base::Bind(&CrosDisksClientImpl::OnFormatCompleted,
235 weak_ptr_factory_.GetWeakPtr(),
236 format_completed_handler),
237 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
238 weak_ptr_factory_.GetWeakPtr()));
239 }
240
[email protected]c5fd5362013-08-27 12:23:04241 protected:
242 virtual void Init(dbus::Bus* bus) OVERRIDE {
243 proxy_ = bus->GetObjectProxy(
244 cros_disks::kCrosDisksServiceName,
245 dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
246 }
247
[email protected]4ae73292011-11-15 05:20:18248 private:
249 // A struct to contain a pair of signal name and mount event type.
[email protected]a0278d52014-05-06 03:36:15250 // Used by SetMountEventHandler.
[email protected]4ae73292011-11-15 05:20:18251 struct SignalEventTuple {
252 const char *signal_name;
253 MountEventType event_type;
254 };
255
256 // Handles the result of Mount and calls |callback| or |error_callback|.
[email protected]5624a252013-07-04 03:17:53257 void OnMount(const base::Closure& callback,
258 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18259 dbus::Response* response) {
260 if (!response) {
261 error_callback.Run();
262 return;
263 }
264 callback.Run();
265 }
266
267 // Handles the result of Unount and calls |callback| or |error_callback|.
[email protected]ffdcc7a9c2013-07-02 06:59:39268 void OnUnmount(const base::Closure& callback,
269 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18270 dbus::Response* response) {
271 if (!response) {
[email protected]ffdcc7a9c2013-07-02 06:59:39272 error_callback.Run();
[email protected]4ae73292011-11-15 05:20:18273 return;
274 }
[email protected]ddcb18e2013-09-19 07:17:28275
276 // Temporarly allow Unmount method to report failure both by setting dbus
277 // error (in which case response is not set) and by returning mount error
278 // different from MOUNT_ERROR_NONE. This is done so we can change Unmount
279 // method to return mount error (http://crbug.com/288974) without breaking
280 // Chrome.
281 // TODO(tbarzic): When Unmount implementation is changed on cros disks side,
282 // make this fail if reader is not able to read the error code value from
283 // the response.
284 dbus::MessageReader reader(response);
[email protected]a0278d52014-05-06 03:36:15285 uint32 error_code = 0;
[email protected]ddcb18e2013-09-19 07:17:28286 if (reader.PopUint32(&error_code) &&
287 static_cast<MountError>(error_code) != MOUNT_ERROR_NONE) {
288 error_callback.Run();
289 return;
290 }
291
[email protected]ffdcc7a9c2013-07-02 06:59:39292 callback.Run();
[email protected]4ae73292011-11-15 05:20:18293 }
294
295 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
296 // |error_callback|.
297 void OnEnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35298 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53299 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18300 dbus::Response* response) {
301 if (!response) {
302 error_callback.Run();
303 return;
304 }
305 dbus::MessageReader reader(response);
306 std::vector<std::string> device_paths;
307 if (!reader.PopArrayOfStrings(&device_paths)) {
308 LOG(ERROR) << "Invalid response: " << response->ToString();
309 error_callback.Run();
310 return;
311 }
312 callback.Run(device_paths);
313 }
314
[email protected]f026c0f2014-05-06 21:52:35315 // Handles the result of Format and calls |callback| or |error_callback|.
316 void OnFormat(const base::Closure& callback,
317 const base::Closure& error_callback,
318 dbus::Response* response) {
[email protected]4ae73292011-11-15 05:20:18319 if (!response) {
320 error_callback.Run();
321 return;
322 }
[email protected]f026c0f2014-05-06 21:52:35323 callback.Run();
[email protected]4ae73292011-11-15 05:20:18324 }
325
326 // Handles the result of GetDeviceProperties and calls |callback| or
327 // |error_callback|.
328 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35329 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53330 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18331 dbus::Response* response) {
332 if (!response) {
333 error_callback.Run();
334 return;
335 }
336 DiskInfo disk(device_path, response);
337 callback.Run(disk);
338 }
339
340 // Handles mount event signals and calls |handler|.
341 void OnMountEvent(MountEventType event_type,
342 MountEventHandler handler,
343 dbus::Signal* signal) {
344 dbus::MessageReader reader(signal);
345 std::string device;
346 if (!reader.PopString(&device)) {
347 LOG(ERROR) << "Invalid signal: " << signal->ToString();
348 return;
349 }
350 handler.Run(event_type, device);
351 }
352
353 // Handles MountCompleted signal and calls |handler|.
354 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
355 dbus::MessageReader reader(signal);
[email protected]a0278d52014-05-06 03:36:15356 uint32 error_code = 0;
[email protected]4ae73292011-11-15 05:20:18357 std::string source_path;
[email protected]a0278d52014-05-06 03:36:15358 uint32 mount_type = 0;
[email protected]4ae73292011-11-15 05:20:18359 std::string mount_path;
360 if (!reader.PopUint32(&error_code) ||
361 !reader.PopString(&source_path) ||
362 !reader.PopUint32(&mount_type) ||
363 !reader.PopString(&mount_path)) {
364 LOG(ERROR) << "Invalid signal: " << signal->ToString();
365 return;
366 }
367 handler.Run(static_cast<MountError>(error_code), source_path,
368 static_cast<MountType>(mount_type), mount_path);
369 }
370
[email protected]a0278d52014-05-06 03:36:15371 // Handles FormatCompleted signal and calls |handler|.
372 void OnFormatCompleted(FormatCompletedHandler handler, dbus::Signal* signal) {
373 dbus::MessageReader reader(signal);
374 uint32 error_code = 0;
375 std::string device_path;
376 if (!reader.PopUint32(&error_code) || !reader.PopString(&device_path)) {
377 LOG(ERROR) << "Invalid signal: " << signal->ToString();
378 return;
379 }
380 handler.Run(static_cast<FormatError>(error_code), device_path);
381 }
382
[email protected]4ae73292011-11-15 05:20:18383 // Handles the result of signal connection setup.
384 void OnSignalConnected(const std::string& interface,
385 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43386 bool succeeded) {
387 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18388 signal << " failed.";
389 }
390
391 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16392
393 // Note: This should remain the last member so it'll be destroyed and
394 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18395 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
396
397 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
398};
399
400// A stub implementaion of CrosDisksClient.
401class CrosDisksClientStubImpl : public CrosDisksClient {
402 public:
[email protected]593cf3b2013-03-05 04:16:52403 CrosDisksClientStubImpl()
[email protected]637c17b82013-04-26 08:13:10404 : weak_ptr_factory_(this) {}
[email protected]593cf3b2013-03-05 04:16:52405
[email protected]4ae73292011-11-15 05:20:18406 virtual ~CrosDisksClientStubImpl() {}
407
[email protected]593cf3b2013-03-05 04:16:52408 // CrosDisksClient overrides:
[email protected]c5fd5362013-08-27 12:23:04409 virtual void Init(dbus::Bus* bus) OVERRIDE {}
[email protected]4ae73292011-11-15 05:20:18410 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48411 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33412 const std::string& mount_label,
[email protected]5624a252013-07-04 03:17:53413 const base::Closure& callback,
414 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52415 // This stub implementation only accepts archive mount requests.
[email protected]44ad4ec2013-07-12 07:56:16416 const MountType type = MOUNT_TYPE_ARCHIVE;
[email protected]593cf3b2013-03-05 04:16:52417
418 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
419 base::FilePath::FromUTF8Unsafe(mount_label));
420
[email protected]be0ed642013-03-07 06:39:32421 // Already mounted path.
422 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
423 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
424 std::string(), callback);
425 return;
426 }
427
[email protected]593cf3b2013-03-05 04:16:52428 // Perform fake mount.
429 base::PostTaskAndReplyWithResult(
[email protected]144b6c42013-06-14 07:30:38430 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
[email protected]593cf3b2013-03-05 04:16:52431 FROM_HERE,
[email protected]144b6c42013-06-14 07:30:38432 base::Bind(&PerformFakeMount, source_path, mounted_path),
[email protected]593cf3b2013-03-05 04:16:52433 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
434 weak_ptr_factory_.GetWeakPtr(),
435 source_path,
436 type,
437 callback,
438 mounted_path));
439 }
440
[email protected]4ae73292011-11-15 05:20:18441 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49442 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39443 const base::Closure& callback,
444 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52445 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32446 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]ffdcc7a9c2013-07-02 06:59:39447 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
[email protected]593cf3b2013-03-05 04:16:52448 return;
449 }
450
[email protected]be0ed642013-03-07 06:39:32451 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52452
453 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32454 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52455 FROM_HERE,
[email protected]dd3aa792013-07-16 19:10:23456 base::Bind(base::IgnoreResult(&base::DeleteFile),
[email protected]be0ed642013-03-07 06:39:32457 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52458 true /* recursive */),
[email protected]ffdcc7a9c2013-07-02 06:59:39459 callback,
[email protected]593cf3b2013-03-05 04:16:52460 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52461 }
462
[email protected]4ae73292011-11-15 05:20:18463 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35464 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53465 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52466 std::vector<std::string> device_paths;
467 base::MessageLoopProxy::current()->PostTask(
468 FROM_HERE, base::Bind(callback, device_paths));
469 }
470
[email protected]f026c0f2014-05-06 21:52:35471 virtual void Format(const std::string& device_path,
472 const std::string& filesystem,
473 const base::Closure& callback,
474 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52475 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
476 }
477
[email protected]4a404e52012-04-11 02:25:35478 virtual void GetDeviceProperties(
479 const std::string& device_path,
480 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53481 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52482 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
483 }
484
[email protected]a0278d52014-05-06 03:36:15485 virtual void SetMountEventHandler(
486 const MountEventHandler& mount_event_handler) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52487 mount_event_handler_ = mount_event_handler;
[email protected]a0278d52014-05-06 03:36:15488 }
489
490 virtual void SetMountCompletedHandler(
491 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52492 mount_completed_handler_ = mount_completed_handler;
493 }
[email protected]4ae73292011-11-15 05:20:18494
[email protected]a0278d52014-05-06 03:36:15495 virtual void SetFormatCompletedHandler(
496 const FormatCompletedHandler& format_completed_handler) OVERRIDE {
497 format_completed_handler_ = format_completed_handler;
498 }
499
[email protected]4ae73292011-11-15 05:20:18500 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.
[email protected]7567484142013-07-11 17:36:07505 if (!base::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
[email protected]593cf3b2013-03-05 04:16:52506 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.
[email protected]426d1c92013-12-03 20:08:54511 if (!base::CreateDirectory(mounted_path)) {
[email protected]593cf3b2013-03-05 04:16:52512 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.";
[email protected]e5c2a22e2014-03-06 20:42:30520 const int write_result = base::WriteFile(
[email protected]593cf3b2013-03-05 04:16:52521 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,
[email protected]5624a252013-07-04 03:17:53534 const base::Closure& callback,
[email protected]593cf3b2013-03-05 04:16:52535 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,
[email protected]5624a252013-07-04 03:17:53552 const base::Closure& callback) {
[email protected]593cf3b2013-03-05 04:16:52553 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_;
[email protected]a0278d52014-05-06 03:36:15567 FormatCompletedHandler format_completed_handler_;
[email protected]593cf3b2013-03-05 04:16:52568
569 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
570
[email protected]4ae73292011-11-15 05:20:18571 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
572};
573
[email protected]85b95a2012012-08-07 18:57:27574} // namespace
[email protected]4ae73292011-11-15 05:20:18575
576////////////////////////////////////////////////////////////////////////////////
577// DiskInfo
578
579DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
580 : device_path_(device_path),
581 is_drive_(false),
582 has_media_(false),
583 on_boot_device_(false),
[email protected]2321d282012-01-31 23:06:59584 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18585 total_size_in_bytes_(0),
586 is_read_only_(false),
587 is_hidden_(true) {
588 InitializeFromResponse(response);
589}
590
591DiskInfo::~DiskInfo() {
592}
593
[email protected]85b95a2012012-08-07 18:57:27594// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18595// Below is an example of |response|'s raw message (long string is ellipsized).
596//
597//
598// message_type: MESSAGE_METHOD_RETURN
599// destination: :1.8
600// sender: :1.16
601// signature: a{sv}
602// serial: 96
603// reply_serial: 267
604//
605// array [
606// dict entry {
607// string "DeviceFile"
608// variant string "/dev/sdb"
609// }
610// dict entry {
611// string "DeviceIsDrive"
612// variant bool true
613// }
614// dict entry {
615// string "DeviceIsMediaAvailable"
616// variant bool true
617// }
618// dict entry {
619// string "DeviceIsMounted"
620// variant bool false
621// }
622// dict entry {
623// string "DeviceIsOnBootDevice"
624// variant bool false
625// }
626// dict entry {
[email protected]4ae73292011-11-15 05:20:18627// string "DeviceIsReadOnly"
628// variant bool false
629// }
630// dict entry {
631// string "DeviceIsVirtual"
632// variant bool false
633// }
634// dict entry {
635// string "DeviceMediaType"
636// variant uint32 1
637// }
638// dict entry {
639// string "DeviceMountPaths"
640// variant array [
641// ]
642// }
643// dict entry {
644// string "DevicePresentationHide"
645// variant bool true
646// }
647// dict entry {
648// string "DeviceSize"
649// variant uint64 7998537728
650// }
651// dict entry {
652// string "DriveIsRotational"
653// variant bool false
654// }
655// dict entry {
[email protected]202e9fee2012-09-13 20:21:29656// string "VendorId"
657// variant string "18d1"
658// }
659// dict entry {
660// string "VendorName"
661// variant string "Google Inc."
662// }
663// dict entry {
664// string "ProductId"
665// variant string "4e11"
666// }
667// dict entry {
668// string "ProductName"
669// variant string "Nexus One"
670// }
671// dict entry {
[email protected]4ae73292011-11-15 05:20:18672// string "DriveModel"
673// variant string "TransMemory"
674// }
675// dict entry {
676// string "IdLabel"
677// variant string ""
678// }
679// dict entry {
680// string "IdUuid"
681// variant string ""
682// }
683// dict entry {
684// string "NativePath"
685// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
686// }
687// ]
688void DiskInfo::InitializeFromResponse(dbus::Response* response) {
[email protected]81836aed2013-07-09 23:41:12689 dbus::MessageReader reader(response);
690 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
691 base::DictionaryValue* properties = NULL;
692 if (!value || !value->GetAsDictionary(&properties))
[email protected]4ae73292011-11-15 05:20:18693 return;
[email protected]4ae73292011-11-15 05:20:18694
[email protected]81836aed2013-07-09 23:41:12695 properties->GetBooleanWithoutPathExpansion(
696 cros_disks::kDeviceIsDrive, &is_drive_);
697 properties->GetBooleanWithoutPathExpansion(
698 cros_disks::kDeviceIsReadOnly, &is_read_only_);
699 properties->GetBooleanWithoutPathExpansion(
700 cros_disks::kDevicePresentationHide, &is_hidden_);
701 properties->GetBooleanWithoutPathExpansion(
702 cros_disks::kDeviceIsMediaAvailable, &has_media_);
703 properties->GetBooleanWithoutPathExpansion(
704 cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
705 properties->GetStringWithoutPathExpansion(
706 cros_disks::kNativePath, &system_path_);
707 properties->GetStringWithoutPathExpansion(
708 cros_disks::kDeviceFile, &file_path_);
709 properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
710 properties->GetStringWithoutPathExpansion(
711 cros_disks::kVendorName, &vendor_name_);
712 properties->GetStringWithoutPathExpansion(
713 cros_disks::kProductId, &product_id_);
714 properties->GetStringWithoutPathExpansion(
715 cros_disks::kProductName, &product_name_);
716 properties->GetStringWithoutPathExpansion(
717 cros_disks::kDriveModel, &drive_model_);
718 properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
719 properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
[email protected]2321d282012-01-31 23:06:59720
[email protected]81836aed2013-07-09 23:41:12721 // dbus::PopDataAsValue() pops uint64 as double.
722 // The top 11 bits of uint64 are dropped by the use of double. But, this works
723 // unless the size exceeds 8 PB.
724 double device_size_double = 0;
725 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
726 &device_size_double))
727 total_size_in_bytes_ = device_size_double;
728
729 // dbus::PopDataAsValue() pops uint32 as double.
730 double media_type_double = 0;
731 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
732 &media_type_double))
733 device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
734
735 base::ListValue* mount_paths = NULL;
736 if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
737 &mount_paths))
738 mount_paths->GetString(0, &mount_path_);
[email protected]4ae73292011-11-15 05:20:18739}
740
741////////////////////////////////////////////////////////////////////////////////
742// CrosDisksClient
743
744CrosDisksClient::CrosDisksClient() {}
745
746CrosDisksClient::~CrosDisksClient() {}
747
748// static
[email protected]c5fd5362013-08-27 12:23:04749CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
[email protected]e8db03d62012-03-31 04:08:38750 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]c5fd5362013-08-27 12:23:04751 return new CrosDisksClientImpl();
[email protected]e8db03d62012-03-31 04:08:38752 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
753 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18754}
755
[email protected]a5a8b412013-03-04 15:03:11756// static
757base::FilePath CrosDisksClient::GetArchiveMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24758 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11759 FILE_PATH_LITERAL("/media/archive") :
760 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
761}
762
763// static
764base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
[email protected]49c4cf852013-09-27 19:28:24765 return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
[email protected]a5a8b412013-03-04 15:03:11766 FILE_PATH_LITERAL("/media/removable") :
767 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
768}
769
[email protected]4ae73292011-11-15 05:20:18770} // namespace chromeos