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

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: Split a part of code into disk_mount_manager.cc/h 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"
25 };
26
27 const char* kDefaultUnmountOptions[] = {
28 "force"
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 // It returns true when a value is popped, false otherwise.
satorux1 2011/11/11 00:43:55 It returns -> Returns
hashimoto 2011/11/11 08:00:53 Done.
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 // It 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 // It 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 // It 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,
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 },
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",
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 // Initialize |this| from |response| given by the cros-disks service.
368 // Below is an example of |response|'s raw message (long string is ellipsized)
369 //
370 //
371 // message_type: MESSAGE_METHOD_RETURN
372 // destination: :1.8
373 // sender: :1.16
374 // signature: a{sv}
375 // serial: 96
376 // reply_serial: 267
377 //
378 // array [
379 // dict entry {
380 // string "DeviceFile"
381 // variant string "/dev/sdb"
382 // }
383 // dict entry {
384 // string "DeviceIsDrive"
385 // variant bool true
386 // }
387 // dict entry {
388 // string "DeviceIsMediaAvailable"
389 // variant bool true
390 // }
391 // dict entry {
392 // string "DeviceIsMounted"
393 // variant bool false
394 // }
395 // dict entry {
396 // string "DeviceIsOnBootDevice"
397 // variant bool false
398 // }
399 // dict entry {
400 // string "DeviceIsOpticalDisc"
401 // variant bool false
402 // }
403 // dict entry {
404 // string "DeviceIsReadOnly"
405 // variant bool false
406 // }
407 // dict entry {
408 // string "DeviceIsVirtual"
409 // variant bool false
410 // }
411 // dict entry {
412 // string "DeviceMediaType"
413 // variant uint32 1
414 // }
415 // dict entry {
416 // string "DeviceMountPaths"
417 // variant array [
418 // ]
419 // }
420 // dict entry {
421 // string "DevicePresentationHide"
422 // variant bool true
423 // }
424 // dict entry {
425 // string "DeviceSize"
426 // variant uint64 7998537728
427 // }
428 // dict entry {
429 // string "DriveIsRotational"
430 // variant bool false
431 // }
432 // dict entry {
433 // string "DriveModel"
434 // variant string "TransMemory"
435 // }
436 // dict entry {
437 // string "IdLabel"
438 // variant string ""
439 // }
440 // dict entry {
441 // string "IdUuid"
442 // variant string ""
443 // }
444 // dict entry {
445 // string "NativePath"
446 // variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
447 // }
448 // ]
449 void DiskInfo::InitializeFromResponse(dbus::Response* response) {
450 dbus::MessageReader response_reader(response);
451 dbus::MessageReader array_reader(response);
452 if (!response_reader.PopArray(&array_reader)) {
453 LOG(ERROR) << "Invalid response: " << response->ToString();
454 return;
455 }
456 // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626
457 ScopedVector<dbus::MessageReader> value_readers_owner;
458 std::map<std::string, dbus::MessageReader*> properties;
459 while (array_reader.HasMoreData()) {
460 // |value_readers_owner| is responsible to delete |value_reader|
461 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
462 value_readers_owner.push_back(value_reader);
463 dbus::MessageReader dict_entry_reader(response);
464 std::string key;
465 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
466 !dict_entry_reader.PopString(&key) ||
467 !dict_entry_reader.PopVariant(value_reader)) {
468 LOG(ERROR) << "Invalid response: " << response->ToString();
469 return;
470 }
471 properties[key] = value_reader;
472 }
473 MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_);
474 MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_);
475 MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_);
476 MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_);
477 MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice],
478 &on_boot_device_);
479 MaybePopString(properties[cros_disks::kNativePath], &system_path_);
480 MaybePopString(properties[cros_disks::kDeviceFile], &file_path_);
481 MaybePopString(properties[cros_disks::kDriveModel], &drive_model_);
482 MaybePopString(properties[cros_disks::kIdLabel], &label_);
483 MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_);
484
485 std::vector<std::string> mount_paths;
486 if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths],
487 &mount_paths) && !mount_paths.empty())
488 mount_path_ = mount_paths[0];
489
490 bool is_rotational = false;
491 bool is_optical = false;
492 if (MaybePopBool(properties[cros_disks::kDriveIsRotational],
493 &is_rotational) &&
494 MaybePopBool(properties[cros_disks::kDeviceIsOpticalDisc],
495 &is_optical))
496 device_type_ = GetDeviceType(is_optical, is_rotational);
497 }
498
499 ////////////////////////////////////////////////////////////////////////////////
500 // CrosDisksClient
501
502 CrosDisksClient::CrosDisksClient() {}
503
504 CrosDisksClient::~CrosDisksClient() {}
505
506 // static
507 CrosDisksClient* CrosDisksClient::Create(dbus::Bus* bus) {
508 CrosDisksClient* impl;
509 if (system::runtime_environment::IsRunningOnChromeOS())
510 impl = new CrosDisksClientImpl(bus);
511 else
512 impl = new CrosDisksClientStubImpl();
513 return impl;
514 }
515
516 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698