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

Side by Side Diff: chromeos/dbus/media_transfer_protocol_daemon_client.cc

Issue 10825170: chromeos: Add dbus MTPDClient. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 4 months 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "chromeos/dbus/media_transfer_protocol_daemon_client.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/stl_util.h"
11 #include "base/stringprintf.h"
12 #include "dbus/bus.h"
13 #include "dbus/message.h"
14 #include "dbus/object_path.h"
15 #include "dbus/object_proxy.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 namespace chromeos {
19
20 namespace {
21
22 // Pops a string value when |reader| is not NULL.
23 // Returns true when a value is popped, false otherwise.
24 bool MaybePopString(dbus::MessageReader* reader, std::string* value) {
25 if (!reader)
26 return false;
27 return reader->PopString(value);
28 }
29
30 // Pops a uint16 value when |reader| is not NULL.
31 // Returns true when a value is popped, false otherwise.
32 bool MaybePopUint16(dbus::MessageReader* reader, uint16* value) {
33 if (!reader)
34 return false;
35 return reader->PopUint16(value);
36 }
37
38 // Pops a uint32 value when |reader| is not NULL.
39 // Returns true when a value is popped, false otherwise.
40 bool MaybePopUint32(dbus::MessageReader* reader, uint32* value) {
41 if (!reader)
42 return false;
43 return reader->PopUint32(value);
44 }
45
46 // Pops a uint64 value when |reader| is not NULL.
47 // Returns true when a value is popped, false otherwise.
48 bool MaybePopUint64(dbus::MessageReader* reader, uint64* value) {
49 if (!reader)
50 return false;
51 return reader->PopUint64(value);
52 }
53
54 // Pops a int64 value when |reader| is not NULL.
55 // Returns true when a value is popped, false otherwise.
56 bool MaybePopInt64(dbus::MessageReader* reader, int64* value) {
57 if (!reader)
58 return false;
59 return reader->PopInt64(value);
60 }
61
62 // The MediaTransferProtocolDaemonClient implementation.
63 class MediaTransferProtocolDaemonClientImpl
64 : public MediaTransferProtocolDaemonClient {
65 public:
66 explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus* bus)
67 : proxy_(bus->GetObjectProxy(
68 mtpd::kMtpdServiceName,
69 dbus::ObjectPath(mtpd::kMtpdServicePath))),
70 weak_ptr_factory_(this) {
71 }
72
73 // MediaTransferProtocolDaemonClient override.
74 virtual void EnumerateStorage(const EnumerateStorageCallback& callback,
75 const ErrorCallback& error_callback) OVERRIDE {
76 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kEnumerateStorage);
77 proxy_->CallMethod(
78 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
79 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorage,
80 weak_ptr_factory_.GetWeakPtr(),
81 callback,
82 error_callback));
83 }
84
85 // MediaTransferProtocolDaemonClient override.
86 virtual void GetStorageInfo(const std::string& storage_name,
87 const GetStorageInfoCallback& callback,
88 const ErrorCallback& error_callback) OVERRIDE {
89 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetStorageInfo);
90 dbus::MessageWriter writer(&method_call);
91 writer.AppendString(storage_name);
92 proxy_->CallMethod(
93 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
94 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo,
95 weak_ptr_factory_.GetWeakPtr(),
96 storage_name,
97 callback,
98 error_callback));
99 }
100
101 // MediaTransferProtocolDaemonClient override.
102 virtual void OpenStorage(const std::string& storage_name,
103 OpenStorageMode mode,
104 const OpenStorageCallback& callback,
105 const ErrorCallback& error_callback) OVERRIDE {
106 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kOpenStorage);
107 dbus::MessageWriter writer(&method_call);
108 writer.AppendString(storage_name);
109 DCHECK_EQ(OPEN_STORAGE_MODE_READ_ONLY, mode);
110 writer.AppendString(mtpd::kReadOnlyMode);
111 proxy_->CallMethod(
112 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
113 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage,
114 weak_ptr_factory_.GetWeakPtr(),
115 callback,
116 error_callback));
117 }
118
119 // MediaTransferProtocolDaemonClient override.
120 virtual void CloseStorage(const std::string& handle,
121 const CloseStorageCallback& callback,
122 const ErrorCallback& error_callback) OVERRIDE {
123 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kCloseStorage);
124 dbus::MessageWriter writer(&method_call);
125 writer.AppendString(handle);
126 proxy_->CallMethod(
127 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
128 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage,
129 weak_ptr_factory_.GetWeakPtr(),
130 callback,
131 error_callback));
132 }
133
134 // MediaTransferProtocolDaemonClient override.
135 virtual void ReadDirectoryByPath(
136 const std::string& handle,
137 const std::string& path,
138 const ReadDirectoryCallback& callback,
139 const ErrorCallback& error_callback) OVERRIDE {
140 dbus::MethodCall method_call(mtpd::kMtpdInterface,
141 mtpd::kReadDirectoryByPath);
142 dbus::MessageWriter writer(&method_call);
143 writer.AppendString(handle);
144 writer.AppendString(path);
145 proxy_->CallMethod(
146 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
147 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory,
148 weak_ptr_factory_.GetWeakPtr(),
149 callback,
150 error_callback));
151 }
152
153 // MediaTransferProtocolDaemonClient override.
154 virtual void ReadDirectoryById(
155 const std::string& handle,
156 uint32 file_id,
157 const ReadDirectoryCallback& callback,
158 const ErrorCallback& error_callback) OVERRIDE {
159 dbus::MethodCall method_call(mtpd::kMtpdInterface,
160 mtpd::kReadDirectoryById);
161 dbus::MessageWriter writer(&method_call);
162 writer.AppendString(handle);
163 writer.AppendUint32(file_id);
164 proxy_->CallMethod(
165 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
166 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory,
167 weak_ptr_factory_.GetWeakPtr(),
168 callback,
169 error_callback));
170 }
171
172 // MediaTransferProtocolDaemonClient override.
173 virtual void ReadFileByPath(const std::string& handle,
174 const std::string& path,
175 const ReadFileCallback& callback,
176 const ErrorCallback& error_callback) OVERRIDE {
177 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kReadFileByPath);
178 dbus::MessageWriter writer(&method_call);
179 writer.AppendString(handle);
180 writer.AppendString(path);
181 proxy_->CallMethod(
182 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
183 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
184 weak_ptr_factory_.GetWeakPtr(),
185 callback,
186 error_callback));
187 }
188
189 // MediaTransferProtocolDaemonClient override.
190 virtual void ReadFileById(const std::string& handle,
191 uint32 file_id,
192 const ReadFileCallback& callback,
193 const ErrorCallback& error_callback) OVERRIDE {
194 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kReadFileById);
195 dbus::MessageWriter writer(&method_call);
196 writer.AppendString(handle);
197 writer.AppendUint32(file_id);
198 proxy_->CallMethod(
199 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
200 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
201 weak_ptr_factory_.GetWeakPtr(),
202 callback,
203 error_callback));
204 }
205
206 // MediaTransferProtocolDaemonClient override.
207 virtual void SetUpConnections(
208 const MTPStorageEventHandler& handler) OVERRIDE {
209 static const SignalEventTuple kSignalEventTuples[] = {
210 { mtpd::kMTPStorageAttached, true },
211 { mtpd::kMTPStorageDetached, false },
212 };
213 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
214
215 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
216 proxy_->ConnectToSignal(
217 mtpd::kMtpdInterface,
218 kSignalEventTuples[i].signal_name,
219 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal,
220 weak_ptr_factory_.GetWeakPtr(),
221 handler,
222 kSignalEventTuples[i].is_attach),
223 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected,
224 weak_ptr_factory_.GetWeakPtr()));
225 }
226 }
227
228 private:
229 // A struct to contain a pair of signal name and attachment event type.
230 // Used by SetUpConnections.
231 struct SignalEventTuple {
232 const char *signal_name;
233 bool is_attach;
234 };
235
236 // Handles the result of EnumerateStorage and calls |callback| or
237 // |error_callback|.
238 void OnEnumerateStorage(const EnumerateStorageCallback& callback,
239 const ErrorCallback& error_callback,
240 dbus::Response* response) {
241 if (!response) {
242 error_callback.Run();
243 return;
244 }
245 dbus::MessageReader reader(response);
246 std::vector<std::string> storage_names;
247 if (!reader.PopArrayOfStrings(&storage_names)) {
248 LOG(ERROR) << "Invalid response: " << response->ToString();
249 error_callback.Run();
250 return;
251 }
252 callback.Run(storage_names);
253 }
254
255 // Handles the result of GetStorageInfo and calls |callback| or
256 // |error_callback|.
257 void OnGetStorageInfo(const std::string& storage_name,
258 const GetStorageInfoCallback& callback,
259 const ErrorCallback& error_callback,
260 dbus::Response* response) {
261 if (!response) {
262 error_callback.Run();
263 return;
264 }
265 StorageInfo storage_info(storage_name, response);
266 callback.Run(storage_info);
267 }
268
269 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
270 void OnOpenStorage(const OpenStorageCallback& callback,
271 const ErrorCallback& error_callback,
272 dbus::Response* response) {
273 if (!response) {
274 error_callback.Run();
275 return;
276 }
277 dbus::MessageReader reader(response);
278 std::string handle;
279 if (!reader.PopString(&handle)) {
280 LOG(ERROR) << "Invalid response: " << response->ToString();
281 error_callback.Run();
282 return;
283 }
284 callback.Run(handle);
285 }
286
287 // Handles the result of CloseStorage and calls |callback| or
288 // |error_callback|.
289 void OnCloseStorage(const CloseStorageCallback& callback,
290 const ErrorCallback& error_callback,
291 dbus::Response* response) {
292 if (!response) {
293 error_callback.Run();
294 return;
295 }
296 callback.Run();
297 }
298
299 // Handles the result of ReadDirectoryByPath/Id and calls |callback| or
300 // |error_callback|.
301 void OnReadDirectory(const ReadDirectoryCallback& callback,
302 const ErrorCallback& error_callback,
303 dbus::Response* response) {
304 if (!response) {
305 error_callback.Run();
306 return;
307 }
308
309 std::vector<FileEntry> file_entries;
310 dbus::MessageReader response_reader(response);
311 dbus::MessageReader array_reader(response);
312 if (!response_reader.PopArray(&array_reader)) {
313 LOG(ERROR) << "Invalid response: " << response->ToString();
314 error_callback.Run();
315 return;
316 }
317 while (array_reader.HasMoreData()) {
318 FileEntry entry(response);
319 file_entries.push_back(entry);
320 }
321 callback.Run(file_entries);
322 }
323
324 // Handles the result of ReadFileByPath/Id and calls |callback| or
325 // |error_callback|.
326 void OnReadFile(const ReadFileCallback& callback,
327 const ErrorCallback& error_callback,
328 dbus::Response* response) {
329 if (!response) {
330 error_callback.Run();
331 return;
332 }
333
334 uint8* data_bytes = NULL;
335 size_t data_length = 0;
336 dbus::MessageReader reader(response);
337 if (!reader.PopArrayOfBytes(&data_bytes, &data_length)) {
338 error_callback.Run();
339 return;
340 }
341 std::string data(reinterpret_cast<const char*>(data_bytes), data_length);
342 callback.Run(data);
343 }
344
345 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
346 void OnMTPStorageSignal(MTPStorageEventHandler handler,
347 bool is_attach,
348 dbus::Signal* signal) {
349 dbus::MessageReader reader(signal);
350 std::string storage_name;
351 if (!reader.PopString(&storage_name)) {
352 LOG(ERROR) << "Invalid signal: " << signal->ToString();
353 return;
354 }
355 DCHECK(!storage_name.empty());
356 handler.Run(is_attach, storage_name);
357 }
358
359
360 // Handles the result of signal connection setup.
361 void OnSignalConnected(const std::string& interface,
362 const std::string& signal,
363 bool successed) {
364 LOG_IF(ERROR, !successed) << "Connect to " << interface << " "
365 << signal << " failed.";
366 }
367
368 dbus::ObjectProxy* proxy_;
369 base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_;
370
371 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl);
372 };
373
374 // A stub implementaion of MediaTransferProtocolDaemonClient.
375 class MediaTransferProtocolDaemonClientStubImpl
376 : public MediaTransferProtocolDaemonClient {
377 public:
378 MediaTransferProtocolDaemonClientStubImpl() {}
379 virtual ~MediaTransferProtocolDaemonClientStubImpl() {}
380
381 virtual void EnumerateStorage(
382 const EnumerateStorageCallback& callback,
383 const ErrorCallback& error_callback) OVERRIDE {}
384 virtual void GetStorageInfo(
385 const std::string& storage_name,
386 const GetStorageInfoCallback& callback,
387 const ErrorCallback& error_callback) OVERRIDE {}
388 virtual void OpenStorage(const std::string& storage_name,
389 OpenStorageMode mode,
390 const OpenStorageCallback& callback,
391 const ErrorCallback& error_callback) OVERRIDE {}
392 virtual void CloseStorage(const std::string& handle,
393 const CloseStorageCallback& callback,
394 const ErrorCallback& error_callback) OVERRIDE {}
395 virtual void ReadDirectoryByPath(
396 const std::string& handle,
397 const std::string& path,
398 const ReadDirectoryCallback& callback,
399 const ErrorCallback& error_callback) OVERRIDE {}
400 virtual void ReadDirectoryById(
401 const std::string& handle,
402 uint32 file_id,
403 const ReadDirectoryCallback& callback,
404 const ErrorCallback& error_callback) OVERRIDE {}
405 virtual void ReadFileByPath(const std::string& handle,
406 const std::string& path,
407 const ReadFileCallback& callback,
408 const ErrorCallback& error_callback) OVERRIDE {}
409 virtual void ReadFileById(const std::string& handle,
410 uint32 file_id,
411 const ReadFileCallback& callback,
412 const ErrorCallback& error_callback) OVERRIDE {}
413 virtual void SetUpConnections(
414 const MTPStorageEventHandler& handler) OVERRIDE {}
415
416 private:
417 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientStubImpl);
418 };
419
420 } // namespace
421
422 ////////////////////////////////////////////////////////////////////////////////
423 // StorageInfo
424
425 StorageInfo::StorageInfo(const std::string& storage_name,
426 dbus::Response* response)
427 : vendor_id_(0),
428 product_id_(0),
429 device_flags_(0),
430 storage_name_(storage_name),
431 storage_type_(0),
432 filesystem_type_(0),
433 access_capability_(0),
434 max_capacity_(0),
435 free_space_in_bytes_(0),
436 free_space_in_objects_(0) {
437 InitializeFromResponse(response);
438 }
439
440 StorageInfo::~StorageInfo() {
441 }
442
443 // Initializes |this| from |response| given by the mtpd service.
444 void StorageInfo::InitializeFromResponse(dbus::Response* response) {
445 dbus::MessageReader response_reader(response);
446 dbus::MessageReader array_reader(response);
447 if (!response_reader.PopArray(&array_reader)) {
448 LOG(ERROR) << "Invalid response: " << response->ToString();
449 return;
450 }
451 // TODO(thestig): Rework this code using Protocol Buffers. crosbug.com/22626
452 typedef std::map<std::string, dbus::MessageReader*> PropertiesMap;
453 PropertiesMap properties;
454 STLValueDeleter<PropertiesMap> properties_value_deleter(&properties);
455 while (array_reader.HasMoreData()) {
456 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
457 dbus::MessageReader dict_entry_reader(response);
458 std::string key;
459 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
460 !dict_entry_reader.PopString(&key) ||
461 !dict_entry_reader.PopVariant(value_reader)) {
462 LOG(ERROR) << "Invalid response: " << response->ToString();
463 return;
464 }
465 properties[key] = value_reader;
466 }
467 // TODO(thestig) Add enums for fields below as appropriate.
468 MaybePopString(properties[mtpd::kVendor], &vendor_);
469 MaybePopString(properties[mtpd::kProduct], &product_);
470 MaybePopString(properties[mtpd::kStorageDescription], &storage_description_);
471 MaybePopString(properties[mtpd::kVolumeIdentifier], &volume_identifier_);
472 MaybePopUint16(properties[mtpd::kVendorId], &vendor_id_);
473 MaybePopUint16(properties[mtpd::kProductId], &product_id_);
474 MaybePopUint16(properties[mtpd::kStorageType], &storage_type_);
475 MaybePopUint16(properties[mtpd::kFilesystemType], &filesystem_type_);
476 MaybePopUint16(properties[mtpd::kAccessCapability], &access_capability_);
477 MaybePopUint32(properties[mtpd::kDeviceFlags], &device_flags_);
478 MaybePopUint64(properties[mtpd::kMaxCapacity], &max_capacity_);
479 MaybePopUint64(properties[mtpd::kFreeSpaceInBytes], &free_space_in_bytes_);
480 MaybePopUint64(properties[mtpd::kFreeSpaceInObjects],
481 &free_space_in_objects_);
482 }
483
484 ////////////////////////////////////////////////////////////////////////////////
485 // FileEntry
486
487 FileEntry::FileEntry(dbus::Response* response)
488 : item_id_(0),
489 parent_id_(0),
490 file_size_(0),
491 file_type_(FILE_TYPE_UNKNOWN) {
492 InitializeFromResponse(response);
493 }
494
495 FileEntry::~FileEntry() {
496 }
497
498 // Initializes |this| from |response| given by the mtpd service.
499 void FileEntry::InitializeFromResponse(dbus::Response* response) {
500 dbus::MessageReader response_reader(response);
501 dbus::MessageReader array_reader(response);
502 if (!response_reader.PopArray(&array_reader)) {
503 LOG(ERROR) << "Invalid response: " << response->ToString();
504 return;
505 }
506 // TODO(thestig): Rework this code using Protocol Buffers. crosbug.com/22626
507 typedef std::map<std::string, dbus::MessageReader*> PropertiesMap;
508 PropertiesMap properties;
509 STLValueDeleter<PropertiesMap> properties_value_deleter(&properties);
510 while (array_reader.HasMoreData()) {
511 dbus::MessageReader* value_reader = new dbus::MessageReader(response);
512 dbus::MessageReader dict_entry_reader(response);
513 std::string key;
514 if (!array_reader.PopDictEntry(&dict_entry_reader) ||
515 !dict_entry_reader.PopString(&key) ||
516 !dict_entry_reader.PopVariant(value_reader)) {
517 LOG(ERROR) << "Invalid response: " << response->ToString();
518 return;
519 }
520 properties[key] = value_reader;
521 }
522
523 MaybePopString(properties[mtpd::kFileName], &file_name_);
524 MaybePopUint32(properties[mtpd::kItemId], &item_id_);
525 MaybePopUint32(properties[mtpd::kParentId], &parent_id_);
526 MaybePopUint64(properties[mtpd::kFileSize], &file_size_);
527
528 int64 modification_date = -1;
529 if (MaybePopInt64(properties[mtpd::kModificationDate], &modification_date))
530 modification_date_ = base::Time::FromTimeT(modification_date);
531
532 uint16 file_type = FILE_TYPE_OTHER;
533 if (MaybePopUint16(properties[mtpd::kFileType], &file_type)) {
534 switch (file_type) {
535 case FILE_TYPE_FOLDER:
536 case FILE_TYPE_JPEG:
537 case FILE_TYPE_JFIF:
538 case FILE_TYPE_TIFF:
539 case FILE_TYPE_BMP:
540 case FILE_TYPE_GIF:
541 case FILE_TYPE_PICT:
542 case FILE_TYPE_PNG:
543 case FILE_TYPE_WINDOWSIMAGEFORMAT:
544 case FILE_TYPE_JP2:
545 case FILE_TYPE_JPX:
546 case FILE_TYPE_UNKNOWN:
547 file_type_ = static_cast<FileType>(file_type);
548 default:
549 file_type_ = FILE_TYPE_OTHER;
550 break;
551 }
552 }
553 }
554
555 ////////////////////////////////////////////////////////////////////////////////
556 // MediaTransferProtocolDaemonClient
557
558 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
559
560 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
561
562 // static
563 MediaTransferProtocolDaemonClient*
564 MediaTransferProtocolDaemonClient::Create(DBusClientImplementationType type,
565 dbus::Bus* bus) {
566 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
567 return new MediaTransferProtocolDaemonClientImpl(bus);
568 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
569 return new MediaTransferProtocolDaemonClientStubImpl();
570 }
571
572 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/dbus/media_transfer_protocol_daemon_client.h ('k') | chromeos/dbus/mock_dbus_thread_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698