blob: 7233786089d7f11a948efa0a71d761ef2f49b079 [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]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.
151 virtual void FormatDevice(const std::string& device_path,
152 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35153 const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53154 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18155 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
156 cros_disks::kFormatDevice);
157 dbus::MessageWriter writer(&method_call);
158 writer.AppendString(device_path);
159 writer.AppendString(filesystem);
160 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
161 base::Bind(&CrosDisksClientImpl::OnFormatDevice,
162 weak_ptr_factory_.GetWeakPtr(),
[email protected]4ae73292011-11-15 05:20:18163 callback,
164 error_callback));
165 }
166
167 // CrosDisksClient override.
[email protected]4a404e52012-04-11 02:25:35168 virtual void GetDeviceProperties(
169 const std::string& device_path,
170 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53171 const base::Closure& error_callback) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18172 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
173 cros_disks::kGetDeviceProperties);
174 dbus::MessageWriter writer(&method_call);
175 writer.AppendString(device_path);
176 proxy_->CallMethod(&method_call,
177 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
178 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
179 weak_ptr_factory_.GetWeakPtr(),
180 device_path,
181 callback,
182 error_callback));
183 }
184
185 // CrosDisksClient override.
186 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35187 const MountEventHandler& mount_event_handler,
188 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
[email protected]4ae73292011-11-15 05:20:18189 static const SignalEventTuple kSignalEventTuples[] = {
[email protected]e3c1fc92012-11-15 00:56:46190 { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
191 { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
192 { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
193 { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
194 { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
195 { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
196 { cros_disks::kFormattingFinished, CROS_DISKS_FORMATTING_FINISHED },
[email protected]4ae73292011-11-15 05:20:18197 };
198 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
199
200 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
201 proxy_->ConnectToSignal(
202 cros_disks::kCrosDisksInterface,
203 kSignalEventTuples[i].signal_name,
204 base::Bind(&CrosDisksClientImpl::OnMountEvent,
205 weak_ptr_factory_.GetWeakPtr(),
206 kSignalEventTuples[i].event_type,
207 mount_event_handler),
208 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
209 weak_ptr_factory_.GetWeakPtr()));
210 }
211 proxy_->ConnectToSignal(
212 cros_disks::kCrosDisksInterface,
[email protected]b3e3f492011-11-18 18:46:00213 cros_disks::kMountCompleted,
[email protected]4ae73292011-11-15 05:20:18214 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
215 weak_ptr_factory_.GetWeakPtr(),
[email protected]85b95a2012012-08-07 18:57:27216 mount_completed_handler),
[email protected]4ae73292011-11-15 05:20:18217 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
218 weak_ptr_factory_.GetWeakPtr()));
219 }
220
[email protected]c5fd5362013-08-27 12:23:04221 protected:
222 virtual void Init(dbus::Bus* bus) OVERRIDE {
223 proxy_ = bus->GetObjectProxy(
224 cros_disks::kCrosDisksServiceName,
225 dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
226 }
227
[email protected]4ae73292011-11-15 05:20:18228 private:
229 // A struct to contain a pair of signal name and mount event type.
230 // Used by SetUpConnections.
231 struct SignalEventTuple {
232 const char *signal_name;
233 MountEventType event_type;
234 };
235
236 // Handles the result of Mount and calls |callback| or |error_callback|.
[email protected]5624a252013-07-04 03:17:53237 void OnMount(const base::Closure& callback,
238 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18239 dbus::Response* response) {
240 if (!response) {
241 error_callback.Run();
242 return;
243 }
244 callback.Run();
245 }
246
247 // Handles the result of Unount and calls |callback| or |error_callback|.
[email protected]ffdcc7a9c2013-07-02 06:59:39248 void OnUnmount(const base::Closure& callback,
249 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18250 dbus::Response* response) {
251 if (!response) {
[email protected]ffdcc7a9c2013-07-02 06:59:39252 error_callback.Run();
[email protected]4ae73292011-11-15 05:20:18253 return;
254 }
[email protected]ffdcc7a9c2013-07-02 06:59:39255 callback.Run();
[email protected]4ae73292011-11-15 05:20:18256 }
257
258 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
259 // |error_callback|.
260 void OnEnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35261 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53262 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18263 dbus::Response* response) {
264 if (!response) {
265 error_callback.Run();
266 return;
267 }
268 dbus::MessageReader reader(response);
269 std::vector<std::string> device_paths;
270 if (!reader.PopArrayOfStrings(&device_paths)) {
271 LOG(ERROR) << "Invalid response: " << response->ToString();
272 error_callback.Run();
273 return;
274 }
275 callback.Run(device_paths);
276 }
277
278 // Handles the result of FormatDevice and calls |callback| or
279 // |error_callback|.
[email protected]15a2c282013-07-03 08:39:49280 void OnFormatDevice(const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53281 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18282 dbus::Response* response) {
283 if (!response) {
284 error_callback.Run();
285 return;
286 }
287 dbus::MessageReader reader(response);
288 bool success = false;
289 if (!reader.PopBool(&success)) {
290 LOG(ERROR) << "Invalid response: " << response->ToString();
291 error_callback.Run();
292 return;
293 }
[email protected]15a2c282013-07-03 08:39:49294 callback.Run(success);
[email protected]4ae73292011-11-15 05:20:18295 }
296
297 // Handles the result of GetDeviceProperties and calls |callback| or
298 // |error_callback|.
299 void OnGetDeviceProperties(const std::string& device_path,
[email protected]4a404e52012-04-11 02:25:35300 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53301 const base::Closure& error_callback,
[email protected]4ae73292011-11-15 05:20:18302 dbus::Response* response) {
303 if (!response) {
304 error_callback.Run();
305 return;
306 }
307 DiskInfo disk(device_path, response);
308 callback.Run(disk);
309 }
310
311 // Handles mount event signals and calls |handler|.
312 void OnMountEvent(MountEventType event_type,
313 MountEventHandler handler,
314 dbus::Signal* signal) {
315 dbus::MessageReader reader(signal);
316 std::string device;
317 if (!reader.PopString(&device)) {
318 LOG(ERROR) << "Invalid signal: " << signal->ToString();
319 return;
320 }
321 handler.Run(event_type, device);
322 }
323
324 // Handles MountCompleted signal and calls |handler|.
325 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
326 dbus::MessageReader reader(signal);
327 unsigned int error_code = 0;
328 std::string source_path;
329 unsigned int mount_type = 0;
330 std::string mount_path;
331 if (!reader.PopUint32(&error_code) ||
332 !reader.PopString(&source_path) ||
333 !reader.PopUint32(&mount_type) ||
334 !reader.PopString(&mount_path)) {
335 LOG(ERROR) << "Invalid signal: " << signal->ToString();
336 return;
337 }
338 handler.Run(static_cast<MountError>(error_code), source_path,
339 static_cast<MountType>(mount_type), mount_path);
340 }
341
342 // Handles the result of signal connection setup.
343 void OnSignalConnected(const std::string& interface,
344 const std::string& signal,
[email protected]d6311dcb2012-10-22 03:40:43345 bool succeeded) {
346 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
[email protected]4ae73292011-11-15 05:20:18347 signal << " failed.";
348 }
349
350 dbus::ObjectProxy* proxy_;
[email protected]926957b2012-09-07 05:34:16351
352 // Note: This should remain the last member so it'll be destroyed and
353 // invalidate its weak pointers before any other members are destroyed.
[email protected]4ae73292011-11-15 05:20:18354 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
355
356 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
357};
358
359// A stub implementaion of CrosDisksClient.
360class CrosDisksClientStubImpl : public CrosDisksClient {
361 public:
[email protected]593cf3b2013-03-05 04:16:52362 CrosDisksClientStubImpl()
[email protected]637c17b82013-04-26 08:13:10363 : weak_ptr_factory_(this) {}
[email protected]593cf3b2013-03-05 04:16:52364
[email protected]4ae73292011-11-15 05:20:18365 virtual ~CrosDisksClientStubImpl() {}
366
[email protected]593cf3b2013-03-05 04:16:52367 // CrosDisksClient overrides:
[email protected]c5fd5362013-08-27 12:23:04368 virtual void Init(dbus::Bus* bus) OVERRIDE {}
[email protected]4ae73292011-11-15 05:20:18369 virtual void Mount(const std::string& source_path,
[email protected]b9f22d12012-04-25 21:46:48370 const std::string& source_format,
[email protected]dcad8fc2012-04-30 23:31:33371 const std::string& mount_label,
[email protected]5624a252013-07-04 03:17:53372 const base::Closure& callback,
373 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52374 // This stub implementation only accepts archive mount requests.
[email protected]44ad4ec2013-07-12 07:56:16375 const MountType type = MOUNT_TYPE_ARCHIVE;
[email protected]593cf3b2013-03-05 04:16:52376
377 const base::FilePath mounted_path = GetArchiveMountPoint().Append(
378 base::FilePath::FromUTF8Unsafe(mount_label));
379
[email protected]be0ed642013-03-07 06:39:32380 // Already mounted path.
381 if (mounted_to_source_path_map_.count(mounted_path.value()) != 0) {
382 FinishMount(MOUNT_ERROR_PATH_ALREADY_MOUNTED, source_path, type,
383 std::string(), callback);
384 return;
385 }
386
[email protected]593cf3b2013-03-05 04:16:52387 // Perform fake mount.
388 base::PostTaskAndReplyWithResult(
[email protected]144b6c42013-06-14 07:30:38389 base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
[email protected]593cf3b2013-03-05 04:16:52390 FROM_HERE,
[email protected]144b6c42013-06-14 07:30:38391 base::Bind(&PerformFakeMount, source_path, mounted_path),
[email protected]593cf3b2013-03-05 04:16:52392 base::Bind(&CrosDisksClientStubImpl::ContinueMount,
393 weak_ptr_factory_.GetWeakPtr(),
394 source_path,
395 type,
396 callback,
397 mounted_path));
398 }
399
[email protected]4ae73292011-11-15 05:20:18400 virtual void Unmount(const std::string& device_path,
[email protected]10795ae2012-10-10 07:33:49401 UnmountOptions options,
[email protected]ffdcc7a9c2013-07-02 06:59:39402 const base::Closure& callback,
403 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52404 // Not mounted.
[email protected]be0ed642013-03-07 06:39:32405 if (mounted_to_source_path_map_.count(device_path) == 0) {
[email protected]ffdcc7a9c2013-07-02 06:59:39406 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
[email protected]593cf3b2013-03-05 04:16:52407 return;
408 }
409
[email protected]be0ed642013-03-07 06:39:32410 mounted_to_source_path_map_.erase(device_path);
[email protected]593cf3b2013-03-05 04:16:52411
412 // Remove the directory created in Mount().
[email protected]be0ed642013-03-07 06:39:32413 base::WorkerPool::PostTaskAndReply(
[email protected]593cf3b2013-03-05 04:16:52414 FROM_HERE,
[email protected]dd3aa792013-07-16 19:10:23415 base::Bind(base::IgnoreResult(&base::DeleteFile),
[email protected]be0ed642013-03-07 06:39:32416 base::FilePath::FromUTF8Unsafe(device_path),
[email protected]593cf3b2013-03-05 04:16:52417 true /* recursive */),
[email protected]ffdcc7a9c2013-07-02 06:59:39418 callback,
[email protected]593cf3b2013-03-05 04:16:52419 true /* task_is_slow */);
[email protected]593cf3b2013-03-05 04:16:52420 }
421
[email protected]4ae73292011-11-15 05:20:18422 virtual void EnumerateAutoMountableDevices(
[email protected]4a404e52012-04-11 02:25:35423 const EnumerateAutoMountableDevicesCallback& callback,
[email protected]5624a252013-07-04 03:17:53424 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52425 std::vector<std::string> device_paths;
426 base::MessageLoopProxy::current()->PostTask(
427 FROM_HERE, base::Bind(callback, device_paths));
428 }
429
[email protected]4ae73292011-11-15 05:20:18430 virtual void FormatDevice(const std::string& device_path,
431 const std::string& filesystem,
[email protected]4a404e52012-04-11 02:25:35432 const FormatDeviceCallback& callback,
[email protected]5624a252013-07-04 03:17:53433 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52434 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
435 }
436
[email protected]4a404e52012-04-11 02:25:35437 virtual void GetDeviceProperties(
438 const std::string& device_path,
439 const GetDevicePropertiesCallback& callback,
[email protected]5624a252013-07-04 03:17:53440 const base::Closure& error_callback) OVERRIDE {
[email protected]593cf3b2013-03-05 04:16:52441 base::MessageLoopProxy::current()->PostTask(FROM_HERE, error_callback);
442 }
443
[email protected]4ae73292011-11-15 05:20:18444 virtual void SetUpConnections(
[email protected]4a404e52012-04-11 02:25:35445 const MountEventHandler& mount_event_handler,
[email protected]593cf3b2013-03-05 04:16:52446 const MountCompletedHandler& mount_completed_handler) OVERRIDE {
447 mount_event_handler_ = mount_event_handler;
448 mount_completed_handler_ = mount_completed_handler;
449 }
[email protected]4ae73292011-11-15 05:20:18450
451 private:
[email protected]593cf3b2013-03-05 04:16:52452 // Performs file actions for Mount().
453 static MountError PerformFakeMount(const std::string& source_path,
454 const base::FilePath& mounted_path) {
455 // Check the source path exists.
[email protected]7567484142013-07-11 17:36:07456 if (!base::PathExists(base::FilePath::FromUTF8Unsafe(source_path))) {
[email protected]593cf3b2013-03-05 04:16:52457 DLOG(ERROR) << "Source does not exist at " << source_path;
458 return MOUNT_ERROR_INVALID_PATH;
459 }
460
461 // Just create an empty directory and shows it as the mounted directory.
462 if (!file_util::CreateDirectory(mounted_path)) {
463 DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
464 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
465 }
466
467 // Put a dummy file.
468 const base::FilePath dummy_file_path =
469 mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
470 const std::string dummy_file_content = "This is a dummy file.";
471 const int write_result = file_util::WriteFile(
472 dummy_file_path, dummy_file_content.data(), dummy_file_content.size());
473 if (write_result != static_cast<int>(dummy_file_content.size())) {
474 DLOG(ERROR) << "Failed to put a dummy file at "
475 << dummy_file_path.value();
476 return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
477 }
478
479 return MOUNT_ERROR_NONE;
480 }
481
482 // Part of Mount() implementation.
483 void ContinueMount(const std::string& source_path,
484 MountType type,
[email protected]5624a252013-07-04 03:17:53485 const base::Closure& callback,
[email protected]593cf3b2013-03-05 04:16:52486 const base::FilePath& mounted_path,
487 MountError mount_error) {
488 if (mount_error != MOUNT_ERROR_NONE) {
489 FinishMount(mount_error, source_path, type, std::string(), callback);
490 return;
491 }
[email protected]be0ed642013-03-07 06:39:32492 mounted_to_source_path_map_[mounted_path.value()] = source_path;
[email protected]593cf3b2013-03-05 04:16:52493 FinishMount(MOUNT_ERROR_NONE, source_path, type,
494 mounted_path.AsUTF8Unsafe(), callback);
495 }
496
497 // Runs |callback| and sends MountCompleted signal.
498 // Part of Mount() implementation.
499 void FinishMount(MountError error,
500 const std::string& source_path,
501 MountType type,
502 const std::string& mounted_path,
[email protected]5624a252013-07-04 03:17:53503 const base::Closure& callback) {
[email protected]593cf3b2013-03-05 04:16:52504 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback);
505 if (!mount_completed_handler_.is_null()) {
506 base::MessageLoopProxy::current()->PostTask(
507 FROM_HERE,
508 base::Bind(mount_completed_handler_,
509 error, source_path, type, mounted_path));
510 }
511 }
512
[email protected]be0ed642013-03-07 06:39:32513 // Mounted path to source path map.
514 std::map<std::string, std::string> mounted_to_source_path_map_;
[email protected]593cf3b2013-03-05 04:16:52515
516 MountEventHandler mount_event_handler_;
517 MountCompletedHandler mount_completed_handler_;
518
519 base::WeakPtrFactory<CrosDisksClientStubImpl> weak_ptr_factory_;
520
[email protected]4ae73292011-11-15 05:20:18521 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
522};
523
[email protected]85b95a2012012-08-07 18:57:27524} // namespace
[email protected]4ae73292011-11-15 05:20:18525
526////////////////////////////////////////////////////////////////////////////////
527// DiskInfo
528
529DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
530 : device_path_(device_path),
531 is_drive_(false),
532 has_media_(false),
533 on_boot_device_(false),
[email protected]2321d282012-01-31 23:06:59534 device_type_(DEVICE_TYPE_UNKNOWN),
[email protected]4ae73292011-11-15 05:20:18535 total_size_in_bytes_(0),
536 is_read_only_(false),
537 is_hidden_(true) {
538 InitializeFromResponse(response);
539}
540
541DiskInfo::~DiskInfo() {
542}
543
[email protected]85b95a2012012-08-07 18:57:27544// Initializes |this| from |response| given by the cros-disks service.
[email protected]4ae73292011-11-15 05:20:18545// Below is an example of |response|'s raw message (long string is ellipsized).
546//
547//
548// message_type: MESSAGE_METHOD_RETURN
549// destination: :1.8
550// sender: :1.16
551// signature: a{sv}
552// serial: 96
553// reply_serial: 267
554//
555// array [
556// dict entry {
557// string "DeviceFile"
558// variant string "/dev/sdb"
559// }
560// dict entry {
561// string "DeviceIsDrive"
562// variant bool true
563// }
564// dict entry {
565// string "DeviceIsMediaAvailable"
566// variant bool true
567// }
568// dict entry {
569// string "DeviceIsMounted"
570// variant bool false
571// }
572// dict entry {
573// string "DeviceIsOnBootDevice"
574// variant bool false
575// }
576// dict entry {
[email protected]4ae73292011-11-15 05:20:18577// string "DeviceIsReadOnly"
578// variant bool false
579// }
580// dict entry {
581// string "DeviceIsVirtual"
582// variant bool false
583// }
584// dict entry {
585// string "DeviceMediaType"
586// variant uint32 1
587// }
588// dict entry {
589// string "DeviceMountPaths"
590// variant array [
591// ]
592// }
593// dict entry {
594// string "DevicePresentationHide"
595// variant bool true
596// }
597// dict entry {
598// string "DeviceSize"
599// variant uint64 7998537728
600// }
601// dict entry {
602// string "DriveIsRotational"
603// variant bool false
604// }
605// dict entry {
[email protected]202e9fee2012-09-13 20:21:29606// string "VendorId"
607// variant string "18d1"
608// }
609// dict entry {
610// string "VendorName"
611// variant string "Google Inc."
612// }
613// dict entry {
614// string "ProductId"
615// variant string "4e11"
616// }
617// dict entry {
618// string "ProductName"
619// variant string "Nexus One"
620// }
621// dict entry {
[email protected]4ae73292011-11-15 05:20:18622// string "DriveModel"
623// variant string "TransMemory"
624// }
625// dict entry {
626// string "IdLabel"
627// variant string ""
628// }
629// dict entry {
630// string "IdUuid"
631// variant string ""
632// }
633// dict entry {
634// string "NativePath"
635// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
636// }
637// ]
638void DiskInfo::InitializeFromResponse(dbus::Response* response) {
[email protected]81836aed2013-07-09 23:41:12639 dbus::MessageReader reader(response);
640 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
641 base::DictionaryValue* properties = NULL;
642 if (!value || !value->GetAsDictionary(&properties))
[email protected]4ae73292011-11-15 05:20:18643 return;
[email protected]4ae73292011-11-15 05:20:18644
[email protected]81836aed2013-07-09 23:41:12645 properties->GetBooleanWithoutPathExpansion(
646 cros_disks::kDeviceIsDrive, &is_drive_);
647 properties->GetBooleanWithoutPathExpansion(
648 cros_disks::kDeviceIsReadOnly, &is_read_only_);
649 properties->GetBooleanWithoutPathExpansion(
650 cros_disks::kDevicePresentationHide, &is_hidden_);
651 properties->GetBooleanWithoutPathExpansion(
652 cros_disks::kDeviceIsMediaAvailable, &has_media_);
653 properties->GetBooleanWithoutPathExpansion(
654 cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
655 properties->GetStringWithoutPathExpansion(
656 cros_disks::kNativePath, &system_path_);
657 properties->GetStringWithoutPathExpansion(
658 cros_disks::kDeviceFile, &file_path_);
659 properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
660 properties->GetStringWithoutPathExpansion(
661 cros_disks::kVendorName, &vendor_name_);
662 properties->GetStringWithoutPathExpansion(
663 cros_disks::kProductId, &product_id_);
664 properties->GetStringWithoutPathExpansion(
665 cros_disks::kProductName, &product_name_);
666 properties->GetStringWithoutPathExpansion(
667 cros_disks::kDriveModel, &drive_model_);
668 properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
669 properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
[email protected]2321d282012-01-31 23:06:59670
[email protected]81836aed2013-07-09 23:41:12671 // dbus::PopDataAsValue() pops uint64 as double.
672 // The top 11 bits of uint64 are dropped by the use of double. But, this works
673 // unless the size exceeds 8 PB.
674 double device_size_double = 0;
675 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
676 &device_size_double))
677 total_size_in_bytes_ = device_size_double;
678
679 // dbus::PopDataAsValue() pops uint32 as double.
680 double media_type_double = 0;
681 if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
682 &media_type_double))
683 device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
684
685 base::ListValue* mount_paths = NULL;
686 if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
687 &mount_paths))
688 mount_paths->GetString(0, &mount_path_);
[email protected]4ae73292011-11-15 05:20:18689}
690
691////////////////////////////////////////////////////////////////////////////////
692// CrosDisksClient
693
694CrosDisksClient::CrosDisksClient() {}
695
696CrosDisksClient::~CrosDisksClient() {}
697
698// static
[email protected]c5fd5362013-08-27 12:23:04699CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
[email protected]e8db03d62012-03-31 04:08:38700 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
[email protected]c5fd5362013-08-27 12:23:04701 return new CrosDisksClientImpl();
[email protected]e8db03d62012-03-31 04:08:38702 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
703 return new CrosDisksClientStubImpl();
[email protected]4ae73292011-11-15 05:20:18704}
705
[email protected]a5a8b412013-03-04 15:03:11706// static
707base::FilePath CrosDisksClient::GetArchiveMountPoint() {
708 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
709 FILE_PATH_LITERAL("/media/archive") :
710 FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
711}
712
713// static
714base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
715 return base::FilePath(base::chromeos::IsRunningOnChromeOS() ?
716 FILE_PATH_LITERAL("/media/removable") :
717 FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
718}
719
[email protected]4ae73292011-11-15 05:20:18720} // namespace chromeos