Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(331)

Side by Side Diff: chrome/browser/chromeos/dbus/cros_disks_client.cc

Issue 8499007: Add CrosDisksClient (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix to please clang Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/dbus/cros_disks_client.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_vector.h"
9 #include "chrome/browser/chromeos/system/runtime_environment.h"
10 #include "dbus/bus.h"
11 #include "dbus/message.h"
12 #include "dbus/object_proxy.h"
13 #include "third_party/cros_system_api/dbus/service_constants.h"
14
15 namespace chromeos {
16
17 namespace {
18
19 const char* kDefaultMountOptions[] = {
20 "rw",
21 "nodev",
22 "noexec",
23 "nosuid",
24 "sync"
satorux1 2011/11/11 19:01:48 you might want to add ,
hashimoto 2011/11/14 13:52:45 Done.
25 };
26
27 const char* kDefaultUnmountOptions[] = {
28 "force"
satorux1 2011/11/11 19:01:48 ditto.
hashimoto 2011/11/14 13:52:45 Done.
29 };
30
31 // Returns the device type from the given arguments.
32 DeviceType GetDeviceType(bool is_optical, bool is_rotational) {
33 if (is_optical)
34 return OPTICAL;
35 if (is_rotational)
36 return HDD;
37 return FLASH;
38 }
39
40 // Pops a bool value when |reader| is not NULL.
41 // Returns true when a value is popped, false otherwise.
42 bool MaybePopBool(dbus::MessageReader* reader, bool* value) {
43 if (!reader)
44 return false;
45 return reader->PopBool(value);
46 }
47
48 // Pops a string value when |reader| is not NULL.
49 // Returns true when a value is popped, false otherwise.
50 bool MaybePopString(dbus::MessageReader* reader, std::string* value) {
51 if (!reader)
52 return false;
53 return reader->PopString(value);
54 }
55
56 // Pops a uint64 value when |reader| is not NULL.
57 // Returns true when a value is popped, false otherwise.
58 bool MaybePopUint64(dbus::MessageReader* reader, uint64* value) {
59 if (!reader)
60 return false;
61 return reader->PopUint64(value);
62 }
63
64 // Pops an array of strings when |reader| is not NULL.
65 // Returns true when an array is popped, false otherwise.
66 bool MaybePopArrayOfStrings(dbus::MessageReader* reader,
67 std::vector<std::string>* value) {
68 if (!reader)
69 return false;
70 return reader->PopArrayOfStrings(value);
71 }
72
73 // The CrosDisksClient implementation
74 class CrosDisksClientImpl : public CrosDisksClient {
75 public:
76 explicit CrosDisksClientImpl(dbus::Bus* bus)
77 : proxy_(bus->GetObjectProxy(cros_disks::kCrosDisksServiceName,
78 cros_disks::kCrosDisksServicePath)),
79 weak_ptr_factory_(this) {
80 }
81
82 virtual void Mount(const std::string& source_path,
satorux1 2011/11/11 19:01:48 // CrosDisksClient override.
hashimoto 2011/11/14 13:52:45 Done.
83 MountType type,
84 MountCallback callback,
85 ErrorCallback error_callback) OVERRIDE {
86 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
87 cros_disks::kMount);
88 dbus::MessageWriter writer(&method_call);
89 writer.AppendString(source_path);
90 writer.AppendString(""); // auto detect filesystem.
91 std::vector<std::string> mount_options(kDefaultMountOptions,
92 kDefaultMountOptions +
93 arraysize(kDefaultMountOptions));
94 writer.AppendArrayOfStrings(mount_options);
95 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
96 base::Bind(&CrosDisksClientImpl::OnMount,
97 weak_ptr_factory_.GetWeakPtr(),
98 callback,
99 error_callback));
100 }
101
102 virtual void Unmount(const std::string& device_path,
103 UnmountCallback callback,
104 ErrorCallback error_callback) OVERRIDE {
105 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
106 cros_disks::kUnmount);
107 dbus::MessageWriter writer(&method_call);
108 writer.AppendString(device_path);
109 std::vector<std::string> unmount_options(kDefaultUnmountOptions,
110 kDefaultUnmountOptions +
111 arraysize(kDefaultUnmountOptions));
112 writer.AppendArrayOfStrings(unmount_options);
113 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
114 base::Bind(&CrosDisksClientImpl::OnUnmount,
115 weak_ptr_factory_.GetWeakPtr(),
116 device_path,
117 callback,
118 error_callback));
119 }
120
121 virtual void EnumerateAutoMountableDevices(
122 EnumerateAutoMountableDevicesCallback callback,
123 ErrorCallback error_callback) OVERRIDE {
124 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
125 cros_disks::kEnumerateAutoMountableDevices);
126 proxy_->CallMethod(
127 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
128 base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
129 weak_ptr_factory_.GetWeakPtr(),
130 callback,
131 error_callback));
132 }
133
134 virtual void FormatDevice(const std::string& device_path,
135 const std::string& filesystem,
136 FormatDeviceCallback callback,
137 ErrorCallback error_callback) OVERRIDE {
138 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
139 cros_disks::kFormatDevice);
140 dbus::MessageWriter writer(&method_call);
141 writer.AppendString(device_path);
142 writer.AppendString(filesystem);
143 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
144 base::Bind(&CrosDisksClientImpl::OnFormatDevice,
145 weak_ptr_factory_.GetWeakPtr(),
146 device_path,
147 callback,
148 error_callback));
149 }
150
151 virtual void GetDeviceProperties(const std::string& device_path,
152 GetDevicePropertiesCallback callback,
153 ErrorCallback error_callback) OVERRIDE {
154 dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
155 cros_disks::kGetDeviceProperties);
156 dbus::MessageWriter writer(&method_call);
157 writer.AppendString(device_path);
158 proxy_->CallMethod(&method_call,
159 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
160 base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
161 weak_ptr_factory_.GetWeakPtr(),
162 device_path,
163 callback,
164 error_callback));
165 }
166
167 virtual void SetUpConnections(
168 MountEventHandler mount_event_handler,
169 MountCompletedHandler mount_completed_handler) OVERRIDE {
170 static const SignalEventTuple kSignalEventTuples[] = {
171 { "DeviceAdded", DEVICE_ADDED },
172 { "DeviceScanned", DEVICE_SCANNED },
173 { "DeviceRemoved", DEVICE_REMOVED },
174 { "DiskAdded", DISK_ADDED },
175 { "DiskChanged", DISK_CHANGED },
176 { "DiskRemoved", DISK_REMOVED },
177 { "FormattingFinished", FORMATTING_FINISHED },
satorux1 2011/11/11 19:01:48 ah, signal names are hard-coded. I'll add constant
hashimoto 2011/11/14 13:52:45 OK, Thanks!
178 };
179 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
180
181 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
182 proxy_->ConnectToSignal(
183 cros_disks::kCrosDisksInterface,
184 kSignalEventTuples[i].signal_name,
185 base::Bind(&CrosDisksClientImpl::OnMountEvent,
186 weak_ptr_factory_.GetWeakPtr(),
187 kSignalEventTuples[i].event_type,
188 mount_event_handler),
189 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
190 weak_ptr_factory_.GetWeakPtr()));
191 }
192 proxy_->ConnectToSignal(
193 cros_disks::kCrosDisksInterface,
194 "MountCompleted",
satorux1 2011/11/11 19:01:48 ditto.
195 base::Bind(&CrosDisksClientImpl::OnMountCompleted,
196 weak_ptr_factory_.GetWeakPtr(),
197 mount_completed_handler ),
198 base::Bind(&CrosDisksClientImpl::OnSignalConnected,
199 weak_ptr_factory_.GetWeakPtr()));
200 }
201
202 private:
203 // A struct to contain a pair of signal name and mount event type.
204 // Used by SetUpConnections.
205 struct SignalEventTuple {
206 const char *signal_name;
207 MountEventType event_type;
208 };
209
210 // Handles the result of Mount and calls |callback| or |error_callback|
211 void OnMount(MountCallback callback,
212 ErrorCallback error_callback,
213 dbus::Response* response) {
214 if (!response) {
215 error_callback.Run();
216 return;
217 }
218 callback.Run();
219 }
220
221 // Handles the result of Unount and calls |callback| or |error_callback|
222 void OnUnmount(const std::string& device_path,
223 UnmountCallback callback,
224 ErrorCallback error_callback,
225 dbus::Response* response) {
226 if (!response) {
227 error_callback.Run();
228 return;
229 }
230 callback.Run(device_path);
231 }
232
233 // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
234 // |error_callback|
235 void OnEnumerateAutoMountableDevices(
236 EnumerateAutoMountableDevicesCallback callback,
237 ErrorCallback error_callback,
238 dbus::Response* response) {
239 if (!response) {
240 error_callback.Run();
241 return;
242 }
243 dbus::MessageReader reader(response);
244 std::vector<std::string> device_paths;
245 if (!reader.PopArrayOfStrings(&device_paths)) {
246 LOG(ERROR) << "Invalid response: " << response->ToString();
247 error_callback.Run();
248 return;
249 }
250 callback.Run(device_paths);
251 }
252
253 // Handles the result of FormatDevice and calls |callback| or |error_callback|
254 void OnFormatDevice(const std::string& device_path,
255 FormatDeviceCallback callback,
256 ErrorCallback error_callback,
257 dbus::Response* response) {
258 if (!response) {
259 error_callback.Run();
260 return;
261 }
262 dbus::MessageReader reader(response);
263 bool success = false;
264 if (!reader.PopBool(&success)) {
265 LOG(ERROR) << "Invalid response: " << response->ToString();
266 error_callback.Run();
267 return;
268 }
269 callback.Run(device_path, success);
270 }
271
272 // Handles the result of GetDeviceProperties and calls |callback| or
273 // |error_callback|
274 void OnGetDeviceProperties(const std::string& device_path,
275 GetDevicePropertiesCallback callback,
276 ErrorCallback error_callback,
277 dbus::Response* response) {
278 if (!response) {
279 error_callback.Run();
280 return;
281 }
282 DiskInfo disk(device_path, response);
283 callback.Run(disk);
284 }
285
286 // Handles mount event signals and calls |handler|
287 void OnMountEvent(MountEventType event_type,
288 MountEventHandler handler,
289 dbus::Signal* signal) {
290 dbus::MessageReader reader(signal);
291 std::string device;
292 if (!reader.PopString(&device)) {
293 LOG(ERROR) << "Invalid signal: " << signal->ToString();
294 return;
295 }
296 handler.Run(event_type, device);
297 }
298
299 // Handles MountCompleted signal and calls |handler|
300 void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
301 dbus::MessageReader reader(signal);
302 unsigned int error_code = 0;
303 std::string source_path;
304 unsigned int mount_type = 0;
305 std::string mount_path;
306 if (!reader.PopUint32(&error_code) ||
307 !reader.PopString(&source_path) ||
308 !reader.PopUint32(&mount_type) ||
309 !reader.PopString(&mount_path)) {
310 LOG(ERROR) << "Invalid signal: " << signal->ToString();
311 return;
312 }
313 handler.Run(static_cast<MountError>(error_code), source_path,
314 static_cast<MountType>(mount_type), mount_path);
315 }
316
317 // Handles the result of signal connection setup.
318 void OnSignalConnected(const std::string& interface,
319 const std::string& signal,
320 bool successed) {
321 LOG_IF(ERROR, !successed) << "Connect to " << interface << " " <<
322 signal << " failed.";
323 }
324
325 dbus::ObjectProxy* proxy_;
326 base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
327
328 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
329 };
330
331 // A stub implementaion of CrosDisksClient
332 class CrosDisksClientStubImpl : public CrosDisksClient {
333 public:
334 CrosDisksClientStubImpl() {}
335 virtual ~CrosDisksClientStubImpl() {}
336
337 virtual void Mount(const std::string& source_path,
338 MountType type,
339 MountCallback callback,
340 ErrorCallback error_callback) OVERRIDE {}
341 virtual void Unmount(const std::string& device_path,
342 UnmountCallback callback,
343 ErrorCallback error_callback) OVERRIDE {}
344 virtual void EnumerateAutoMountableDevices(
345 EnumerateAutoMountableDevicesCallback callback,
346 ErrorCallback error_callback) OVERRIDE {}
347 virtual void FormatDevice(const std::string& device_path,
348 const std::string& filesystem,
349 FormatDeviceCallback callback,
350 ErrorCallback error_callback) OVERRIDE {}
351 virtual void GetDeviceProperties(const std::string& device_path,
352 GetDevicePropertiesCallback callback,
353 ErrorCallback error_callback) OVERRIDE {}
354 virtual void SetUpConnections(
355 MountEventHandler mount_event_handler,
356 MountCompletedHandler mount_completed_handler) OVERRIDE {}
357
358 private:
359 DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl);
360 };
361
362 } // namespace
363
364 ////////////////////////////////////////////////////////////////////////////////
365 // DiskInfo
366
367 DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
368 : device_path_(device_path),
369 is_drive_(false),
370 has_media_(false),
371 on_boot_device_(false),
372 device_type_(UNDEFINED),
373 total_size_in_bytes_(0),
374 is_read_only_(false),
375 is_hidden_(true) {
376 InitializeFromResponse(response);
377 }
378
379 DiskInfo::~DiskInfo() {
380 }
381
382 // Initialize |this| from |response| given by the cros-disks service.
383 // Below is an example of |response|'s raw message (long string is ellipsized)
384 //
385 //
386 // message_type: MESSAGE_METHOD_RETURN
387 // destination: :1.8
388 // sender: :1.16
389 // signature: a{sv}
390 // serial: 96
391 // reply_serial: 267
392 //
393 // array [
394 // dict entry {
395 // string "DeviceFile"
396 // variant string "/dev/sdb"
397 // }
398 // dict entry {
399 // string "DeviceIsDrive"
400 // variant bool true
401 // }
402 // dict entry {
403 // string "DeviceIsMediaAvailable"
404 // variant bool true
405 // }
406 // dict entry {
407 // string "DeviceIsMounted"
408 // variant bool false
409 // }
410 // dict entry {
411 // string "DeviceIsOnBootDevice"
412 // variant bool false
413 // }
414 // dict entry {
415 // string "DeviceIsOpticalDisc"
416 // variant bool false
417 // }
418 // dict entry {
419 // string "DeviceIsReadOnly"
420 // variant bool false
421 // }
422 // dict entry {
423 // string "DeviceIsVirtual"
424 // variant bool false
425 // }
426 // dict entry {
427 // string "DeviceMediaType"
428 // variant uint32 1
429 // }
430 // dict entry {
431 // string "DeviceMountPaths"
432 // variant array [
433 // ]
434 // }
435 // dict entry {
436 // string "DevicePresentationHide"
437 // variant bool true
438 // }
439 // dict entry {
440 // string "DeviceSize"
441 // variant uint64 7998537728
442 // }
443 // dict entry {
444 // string "DriveIsRotational"
445 // variant bool false
446 // }
447 // dict entry {
448 // string "DriveModel"
449 // variant string "TransMemory"
450 // }
451 // dict entry {
452 // string "IdLabel"
453 // variant string ""
454 // }
455 // dict entry {
456 // string "IdUuid"
457 // variant string ""
458 // }
459 // dict entry {
460 // string "NativePath"
461 // variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
462 // }
463 // ]
464 void DiskInfo::InitializeFromResponse(dbus::Response* response) {
465 dbus::MessageReader response_reader(response);
466 dbus::MessageReader array_reader(response);
467 if (!response_reader.PopArray(&array_reader)) {
468 LOG(ERROR) << "Invalid response: " << response->ToString();
469 return;
470 }
471 // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
472 ScopedVector<dbus::MessageReader> value_readers_owner;
473 std::map<std::string, dbus::MessageReader*> properties;
474 while (array_reader.HasMoreData()) {
475 // |value_readers_owner| is responsible to delete |value_reader|
476 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
477 value_readers_owner.push_back(value_reader);
478 dbus::MessageReader dict_entry_reader(response);
479 std::string key;
480 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
481 !dict_entry_reader.PopString(&key) ||
482 !dict_entry_reader.PopVariant(value_reader)) {
483 LOG(ERROR) << "Invalid response: " << response->ToString();
484 return;
485 }
486 properties[key] = value_reader;
487 }
488 MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
489 MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
490 MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
491 MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
492 MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
493 &on_boot_device_);
494 MaybePopString(properties[cros_disks::kNativePath], &system_path_);
495 MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
496 MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
497 MaybePopString(properties[cros_disks::kIdLabel], &label_);
498 MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_);
499
500 std::vector<std::string> mount_paths;
501 if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
502 &mount_paths) && !mount_paths.empty())
503 mount_path_ = mount_paths[0];
504
505 bool is_rotational = false;
506 bool is_optical = false;
507 if (MaybePopBool(properties[cros_disks::kDriveIsRotational],
508 &is_rotational) &&
509 MaybePopBool(properties[cros_disks::kDeviceIsOpticalDisc],
510 &is_optical))
511 device_type_ = GetDeviceType(is_optical, is_rotational);
512 }
513
514 ////////////////////////////////////////////////////////////////////////////////
515 // CrosDisksClient
516
517 CrosDisksClient::CrosDisksClient() {}
518
519 CrosDisksClient::~CrosDisksClient() {}
520
521 // static
522 CrosDisksClient* CrosDisksClient::Create(dbus::Bus* bus) {
523 CrosDisksClient* impl;
satorux1 2011/11/11 19:01:48 = NULL; just in case.
524 if (system::runtime_environment::IsRunningOnChromeOS())
525 impl = new CrosDisksClientImpl(bus);
satorux1 2011/11/11 19:01:48 return new CrosDisksClientImpl(bus); may be simpl
hashimoto 2011/11/14 13:52:45 Done.
526 else
527 impl = new CrosDisksClientStubImpl();
528 return impl;
529 }
530
531 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698