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 ReadDirectoryById(
100 const std::string
& handle
,
102 const ReadDirectoryCallback
& callback
,
103 const ErrorCallback
& error_callback
) OVERRIDE
{
104 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
105 mtpd::kReadDirectoryById
);
106 dbus::MessageWriter
writer(&method_call
);
107 writer
.AppendString(handle
);
108 writer
.AppendUint32(file_id
);
110 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
111 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory
,
112 weak_ptr_factory_
.GetWeakPtr(),
117 // MediaTransferProtocolDaemonClient override.
118 virtual void ReadFileChunkById(const std::string
& handle
,
121 uint32 bytes_to_read
,
122 const ReadFileCallback
& callback
,
123 const ErrorCallback
& error_callback
) OVERRIDE
{
124 DCHECK_LE(bytes_to_read
, kMaxChunkSize
);
125 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
126 mtpd::kReadFileChunkById
);
127 dbus::MessageWriter
writer(&method_call
);
128 writer
.AppendString(handle
);
129 writer
.AppendUint32(file_id
);
130 writer
.AppendUint32(offset
);
131 writer
.AppendUint32(bytes_to_read
);
133 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
134 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile
,
135 weak_ptr_factory_
.GetWeakPtr(),
140 // MediaTransferProtocolDaemonClient override.
141 virtual void GetFileInfoById(const std::string
& handle
,
143 const GetFileInfoCallback
& callback
,
144 const ErrorCallback
& error_callback
) OVERRIDE
{
145 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kGetFileInfoById
);
146 dbus::MessageWriter
writer(&method_call
);
147 writer
.AppendString(handle
);
148 writer
.AppendUint32(file_id
);
150 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
151 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo
,
152 weak_ptr_factory_
.GetWeakPtr(),
157 // MediaTransferProtocolDaemonClient override.
158 virtual void ListenForChanges(
159 const MTPStorageEventHandler
& handler
) OVERRIDE
{
160 DCHECK(!listen_for_changes_called_
);
161 listen_for_changes_called_
= true;
163 static const SignalEventTuple kSignalEventTuples
[] = {
164 { mtpd::kMTPStorageAttached
, true },
165 { mtpd::kMTPStorageDetached
, false },
167 const size_t kNumSignalEventTuples
= arraysize(kSignalEventTuples
);
169 for (size_t i
= 0; i
< kNumSignalEventTuples
; ++i
) {
170 proxy_
->ConnectToSignal(
171 mtpd::kMtpdInterface
,
172 kSignalEventTuples
[i
].signal_name
,
173 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal
,
174 weak_ptr_factory_
.GetWeakPtr(),
176 kSignalEventTuples
[i
].is_attach
),
177 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected
,
178 weak_ptr_factory_
.GetWeakPtr()));
183 // A struct to contain a pair of signal name and attachment event type.
184 // Used by SetUpConnections.
185 struct SignalEventTuple
{
186 const char *signal_name
;
190 // Handles the result of EnumerateStorages and calls |callback| or
192 void OnEnumerateStorages(const EnumerateStoragesCallback
& callback
,
193 const ErrorCallback
& error_callback
,
194 dbus::Response
* response
) {
196 error_callback
.Run();
199 dbus::MessageReader
reader(response
);
200 std::vector
<std::string
> storage_names
;
201 if (!reader
.PopArrayOfStrings(&storage_names
)) {
202 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
203 error_callback
.Run();
206 callback
.Run(storage_names
);
209 // Handles the result of GetStorageInfo and calls |callback| or
211 void OnGetStorageInfo(const std::string
& storage_name
,
212 const GetStorageInfoCallback
& callback
,
213 const ErrorCallback
& error_callback
,
214 dbus::Response
* response
) {
215 LOG(ERROR
) << "Client OnGetStorageInfo " << storage_name
;
217 error_callback
.Run();
221 dbus::MessageReader
reader(response
);
222 MtpStorageInfo protobuf
;
223 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
224 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
225 error_callback
.Run();
228 callback
.Run(protobuf
);
231 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
232 void OnOpenStorage(const OpenStorageCallback
& callback
,
233 const ErrorCallback
& error_callback
,
234 dbus::Response
* response
) {
236 error_callback
.Run();
239 dbus::MessageReader
reader(response
);
241 if (!reader
.PopString(&handle
)) {
242 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
243 error_callback
.Run();
246 callback
.Run(handle
);
249 // Handles the result of CloseStorage and calls |callback| or
251 void OnCloseStorage(const CloseStorageCallback
& callback
,
252 const ErrorCallback
& error_callback
,
253 dbus::Response
* response
) {
255 error_callback
.Run();
261 // Handles the result of ReadDirectoryById and calls |callback| or
263 void OnReadDirectory(const ReadDirectoryCallback
& callback
,
264 const ErrorCallback
& error_callback
,
265 dbus::Response
* response
) {
267 error_callback
.Run();
271 std::vector
<MtpFileEntry
> file_entries
;
272 dbus::MessageReader
reader(response
);
273 MtpFileEntries entries_protobuf
;
274 if (!reader
.PopArrayOfBytesAsProto(&entries_protobuf
)) {
275 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
276 error_callback
.Run();
280 for (int i
= 0; i
< entries_protobuf
.file_entries_size(); ++i
)
281 file_entries
.push_back(entries_protobuf
.file_entries(i
));
282 callback
.Run(file_entries
);
285 // Handles the result of ReadFileChunkById and calls |callback| or
287 void OnReadFile(const ReadFileCallback
& callback
,
288 const ErrorCallback
& error_callback
,
289 dbus::Response
* response
) {
291 error_callback
.Run();
295 const uint8
* data_bytes
= NULL
;
296 size_t data_length
= 0;
297 dbus::MessageReader
reader(response
);
298 if (!reader
.PopArrayOfBytes(&data_bytes
, &data_length
)) {
299 error_callback
.Run();
302 std::string
data(reinterpret_cast<const char*>(data_bytes
), data_length
);
306 // Handles the result of GetFileInfoById and calls |callback| or
308 void OnGetFileInfo(const GetFileInfoCallback
& callback
,
309 const ErrorCallback
& error_callback
,
310 dbus::Response
* response
) {
312 error_callback
.Run();
316 dbus::MessageReader
reader(response
);
317 MtpFileEntry protobuf
;
318 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
319 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
320 error_callback
.Run();
323 callback
.Run(protobuf
);
326 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
327 void OnMTPStorageSignal(MTPStorageEventHandler handler
,
329 dbus::Signal
* signal
) {
330 dbus::MessageReader
reader(signal
);
331 std::string storage_name
;
332 if (!reader
.PopString(&storage_name
)) {
333 LOG(ERROR
) << "Invalid signal: " << signal
->ToString();
336 DCHECK(!storage_name
.empty());
337 handler
.Run(is_attach
, storage_name
);
341 // Handles the result of signal connection setup.
342 void OnSignalConnected(const std::string
& interface
,
343 const std::string
& signal
,
345 LOG_IF(ERROR
, !succeeded
) << "Connect to " << interface
<< " "
346 << signal
<< " failed.";
349 dbus::ObjectProxy
* proxy_
;
351 bool listen_for_changes_called_
;
353 // Note: This should remain the last member so it'll be destroyed and
354 // invalidate its weak pointers before any other members are destroyed.
355 base::WeakPtrFactory
<MediaTransferProtocolDaemonClientImpl
> weak_ptr_factory_
;
357 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl
);
362 ////////////////////////////////////////////////////////////////////////////////
363 // MediaTransferProtocolDaemonClient
365 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
367 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
370 MediaTransferProtocolDaemonClient
* MediaTransferProtocolDaemonClient::Create(
372 return new MediaTransferProtocolDaemonClientImpl(bus
);
375 } // namespace device