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.
5 #include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h"
8 #include "base/memory/weak_ptr.h"
10 #include "dbus/message.h"
11 #include "dbus/object_path.h"
12 #include "dbus/object_proxy.h"
13 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
14 #include "device/media_transfer_protocol/mtp_storage_info.pb.h"
15 #include "third_party/cros_system_api/dbus/service_constants.h"
21 const char kInvalidResponseMsg
[] = "Invalid Response: ";
22 uint32 kMaxChunkSize
= 1024*1024; // D-Bus has message size limits.
24 // The MediaTransferProtocolDaemonClient implementation.
25 class MediaTransferProtocolDaemonClientImpl
26 : public MediaTransferProtocolDaemonClient
{
28 explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus
* bus
)
29 : proxy_(bus
->GetObjectProxy(
30 mtpd::kMtpdServiceName
,
31 dbus::ObjectPath(mtpd::kMtpdServicePath
))),
32 listen_for_changes_called_(false),
33 weak_ptr_factory_(this) {
36 // MediaTransferProtocolDaemonClient override.
37 virtual void EnumerateStorages(const EnumerateStoragesCallback
& callback
,
38 const ErrorCallback
& error_callback
) OVERRIDE
{
39 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
40 mtpd::kEnumerateStorages
);
42 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
43 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorages
,
44 weak_ptr_factory_
.GetWeakPtr(),
49 // MediaTransferProtocolDaemonClient override.
50 virtual void GetStorageInfo(const std::string
& storage_name
,
51 const GetStorageInfoCallback
& callback
,
52 const ErrorCallback
& error_callback
) OVERRIDE
{
53 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kGetStorageInfo
);
54 dbus::MessageWriter
writer(&method_call
);
55 writer
.AppendString(storage_name
);
57 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
58 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo
,
59 weak_ptr_factory_
.GetWeakPtr(),
65 // MediaTransferProtocolDaemonClient override.
66 virtual void OpenStorage(const std::string
& storage_name
,
67 const std::string
& mode
,
68 const OpenStorageCallback
& callback
,
69 const ErrorCallback
& error_callback
) OVERRIDE
{
70 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kOpenStorage
);
71 dbus::MessageWriter
writer(&method_call
);
72 writer
.AppendString(storage_name
);
73 DCHECK_EQ(mtpd::kReadOnlyMode
, mode
);
74 writer
.AppendString(mtpd::kReadOnlyMode
);
76 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
77 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage
,
78 weak_ptr_factory_
.GetWeakPtr(),
83 // MediaTransferProtocolDaemonClient override.
84 virtual void CloseStorage(const std::string
& handle
,
85 const CloseStorageCallback
& callback
,
86 const ErrorCallback
& error_callback
) OVERRIDE
{
87 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kCloseStorage
);
88 dbus::MessageWriter
writer(&method_call
);
89 writer
.AppendString(handle
);
91 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
92 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage
,
93 weak_ptr_factory_
.GetWeakPtr(),
98 // MediaTransferProtocolDaemonClient override.
99 virtual void ReadDirectoryByPath(
100 const std::string
& handle
,
101 const std::string
& path
,
102 const ReadDirectoryCallback
& callback
,
103 const ErrorCallback
& error_callback
) OVERRIDE
{
104 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
105 mtpd::kReadDirectoryByPath
);
106 dbus::MessageWriter
writer(&method_call
);
107 writer
.AppendString(handle
);
108 writer
.AppendString(path
);
110 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
111 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory
,
112 weak_ptr_factory_
.GetWeakPtr(),
117 // MediaTransferProtocolDaemonClient override.
118 virtual void ReadDirectoryById(
119 const std::string
& handle
,
121 const ReadDirectoryCallback
& callback
,
122 const ErrorCallback
& error_callback
) OVERRIDE
{
123 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
124 mtpd::kReadDirectoryById
);
125 dbus::MessageWriter
writer(&method_call
);
126 writer
.AppendString(handle
);
127 writer
.AppendUint32(file_id
);
129 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
130 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory
,
131 weak_ptr_factory_
.GetWeakPtr(),
136 // MediaTransferProtocolDaemonClient override.
137 virtual void ReadFileChunkByPath(
138 const std::string
& handle
,
139 const std::string
& path
,
141 uint32 bytes_to_read
,
142 const ReadFileCallback
& callback
,
143 const ErrorCallback
& error_callback
) OVERRIDE
{
144 DCHECK_LE(bytes_to_read
, kMaxChunkSize
);
145 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
146 mtpd::kReadFileChunkByPath
);
147 dbus::MessageWriter
writer(&method_call
);
148 writer
.AppendString(handle
);
149 writer
.AppendString(path
);
150 writer
.AppendUint32(offset
);
151 writer
.AppendUint32(bytes_to_read
);
153 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
154 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile
,
155 weak_ptr_factory_
.GetWeakPtr(),
160 // MediaTransferProtocolDaemonClient override.
161 virtual void ReadFileChunkById(const std::string
& handle
,
164 uint32 bytes_to_read
,
165 const ReadFileCallback
& callback
,
166 const ErrorCallback
& error_callback
) OVERRIDE
{
167 DCHECK_LE(bytes_to_read
, kMaxChunkSize
);
168 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
169 mtpd::kReadFileChunkById
);
170 dbus::MessageWriter
writer(&method_call
);
171 writer
.AppendString(handle
);
172 writer
.AppendUint32(file_id
);
173 writer
.AppendUint32(offset
);
174 writer
.AppendUint32(bytes_to_read
);
176 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
177 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile
,
178 weak_ptr_factory_
.GetWeakPtr(),
183 // MediaTransferProtocolDaemonClient override.
184 virtual void GetFileInfoByPath(const std::string
& handle
,
185 const std::string
& path
,
186 const GetFileInfoCallback
& callback
,
187 const ErrorCallback
& error_callback
) OVERRIDE
{
188 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
189 mtpd::kGetFileInfoByPath
);
190 dbus::MessageWriter
writer(&method_call
);
191 writer
.AppendString(handle
);
192 writer
.AppendString(path
);
194 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
195 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo
,
196 weak_ptr_factory_
.GetWeakPtr(),
201 // MediaTransferProtocolDaemonClient override.
202 virtual void GetFileInfoById(const std::string
& handle
,
204 const GetFileInfoCallback
& callback
,
205 const ErrorCallback
& error_callback
) OVERRIDE
{
206 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kGetFileInfoById
);
207 dbus::MessageWriter
writer(&method_call
);
208 writer
.AppendString(handle
);
209 writer
.AppendUint32(file_id
);
211 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
212 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo
,
213 weak_ptr_factory_
.GetWeakPtr(),
218 // MediaTransferProtocolDaemonClient override.
219 virtual void ListenForChanges(
220 const MTPStorageEventHandler
& handler
) OVERRIDE
{
221 DCHECK(!listen_for_changes_called_
);
222 listen_for_changes_called_
= true;
224 static const SignalEventTuple kSignalEventTuples
[] = {
225 { mtpd::kMTPStorageAttached
, true },
226 { mtpd::kMTPStorageDetached
, false },
228 const size_t kNumSignalEventTuples
= arraysize(kSignalEventTuples
);
230 for (size_t i
= 0; i
< kNumSignalEventTuples
; ++i
) {
231 proxy_
->ConnectToSignal(
232 mtpd::kMtpdInterface
,
233 kSignalEventTuples
[i
].signal_name
,
234 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal
,
235 weak_ptr_factory_
.GetWeakPtr(),
237 kSignalEventTuples
[i
].is_attach
),
238 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected
,
239 weak_ptr_factory_
.GetWeakPtr()));
244 // A struct to contain a pair of signal name and attachment event type.
245 // Used by SetUpConnections.
246 struct SignalEventTuple
{
247 const char *signal_name
;
251 // Handles the result of EnumerateStorages and calls |callback| or
253 void OnEnumerateStorages(const EnumerateStoragesCallback
& callback
,
254 const ErrorCallback
& error_callback
,
255 dbus::Response
* response
) {
257 error_callback
.Run();
260 dbus::MessageReader
reader(response
);
261 std::vector
<std::string
> storage_names
;
262 if (!reader
.PopArrayOfStrings(&storage_names
)) {
263 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
264 error_callback
.Run();
267 callback
.Run(storage_names
);
270 // Handles the result of GetStorageInfo and calls |callback| or
272 void OnGetStorageInfo(const std::string
& storage_name
,
273 const GetStorageInfoCallback
& callback
,
274 const ErrorCallback
& error_callback
,
275 dbus::Response
* response
) {
277 error_callback
.Run();
281 dbus::MessageReader
reader(response
);
282 MtpStorageInfo protobuf
;
283 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
284 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
285 error_callback
.Run();
288 callback
.Run(protobuf
);
291 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
292 void OnOpenStorage(const OpenStorageCallback
& callback
,
293 const ErrorCallback
& error_callback
,
294 dbus::Response
* response
) {
296 error_callback
.Run();
299 dbus::MessageReader
reader(response
);
301 if (!reader
.PopString(&handle
)) {
302 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
303 error_callback
.Run();
306 callback
.Run(handle
);
309 // Handles the result of CloseStorage and calls |callback| or
311 void OnCloseStorage(const CloseStorageCallback
& callback
,
312 const ErrorCallback
& error_callback
,
313 dbus::Response
* response
) {
315 error_callback
.Run();
321 // Handles the result of ReadDirectoryByPath/Id and calls |callback| or
323 void OnReadDirectory(const ReadDirectoryCallback
& callback
,
324 const ErrorCallback
& error_callback
,
325 dbus::Response
* response
) {
327 error_callback
.Run();
331 std::vector
<MtpFileEntry
> file_entries
;
332 dbus::MessageReader
reader(response
);
333 MtpFileEntries entries_protobuf
;
334 if (!reader
.PopArrayOfBytesAsProto(&entries_protobuf
)) {
335 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
336 error_callback
.Run();
340 for (int i
= 0; i
< entries_protobuf
.file_entries_size(); ++i
)
341 file_entries
.push_back(entries_protobuf
.file_entries(i
));
342 callback
.Run(file_entries
);
345 // Handles the result of ReadFileChunkByPath/Id and calls |callback| or
347 void OnReadFile(const ReadFileCallback
& callback
,
348 const ErrorCallback
& error_callback
,
349 dbus::Response
* response
) {
351 error_callback
.Run();
355 const uint8
* data_bytes
= NULL
;
356 size_t data_length
= 0;
357 dbus::MessageReader
reader(response
);
358 if (!reader
.PopArrayOfBytes(&data_bytes
, &data_length
)) {
359 error_callback
.Run();
362 std::string
data(reinterpret_cast<const char*>(data_bytes
), data_length
);
366 // Handles the result of GetFileInfoByPath/Id and calls |callback| or
368 void OnGetFileInfo(const GetFileInfoCallback
& callback
,
369 const ErrorCallback
& error_callback
,
370 dbus::Response
* response
) {
372 error_callback
.Run();
376 dbus::MessageReader
reader(response
);
377 MtpFileEntry protobuf
;
378 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
379 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
380 error_callback
.Run();
383 callback
.Run(protobuf
);
386 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
387 void OnMTPStorageSignal(MTPStorageEventHandler handler
,
389 dbus::Signal
* signal
) {
390 dbus::MessageReader
reader(signal
);
391 std::string storage_name
;
392 if (!reader
.PopString(&storage_name
)) {
393 LOG(ERROR
) << "Invalid signal: " << signal
->ToString();
396 DCHECK(!storage_name
.empty());
397 handler
.Run(is_attach
, storage_name
);
401 // Handles the result of signal connection setup.
402 void OnSignalConnected(const std::string
& interface
,
403 const std::string
& signal
,
405 LOG_IF(ERROR
, !succeeded
) << "Connect to " << interface
<< " "
406 << signal
<< " failed.";
409 dbus::ObjectProxy
* proxy_
;
411 bool listen_for_changes_called_
;
413 // Note: This should remain the last member so it'll be destroyed and
414 // invalidate its weak pointers before any other members are destroyed.
415 base::WeakPtrFactory
<MediaTransferProtocolDaemonClientImpl
> weak_ptr_factory_
;
417 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl
);
422 ////////////////////////////////////////////////////////////////////////////////
423 // MediaTransferProtocolDaemonClient
425 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
427 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
430 MediaTransferProtocolDaemonClient
* MediaTransferProtocolDaemonClient::Create(
432 return new MediaTransferProtocolDaemonClientImpl(bus
);
435 } // namespace device