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

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

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

Powered by Google App Engine
This is Rietveld 408576698