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: ";
23 // The MediaTransferProtocolDaemonClient implementation.
24 class MediaTransferProtocolDaemonClientImpl
25 : public MediaTransferProtocolDaemonClient
{
27 explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus
* bus
)
28 : proxy_(bus
->GetObjectProxy(
29 mtpd::kMtpdServiceName
,
30 dbus::ObjectPath(mtpd::kMtpdServicePath
))),
31 listen_for_changes_called_(false),
32 weak_ptr_factory_(this) {
35 // MediaTransferProtocolDaemonClient override.
36 virtual void EnumerateStorages(const EnumerateStoragesCallback
& callback
,
37 const ErrorCallback
& error_callback
) OVERRIDE
{
38 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
39 mtpd::kEnumerateStorages
);
41 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
42 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorages
,
43 weak_ptr_factory_
.GetWeakPtr(),
48 // MediaTransferProtocolDaemonClient override.
49 virtual void GetStorageInfo(const std::string
& storage_name
,
50 const GetStorageInfoCallback
& callback
,
51 const ErrorCallback
& error_callback
) OVERRIDE
{
52 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kGetStorageInfo
);
53 dbus::MessageWriter
writer(&method_call
);
54 writer
.AppendString(storage_name
);
56 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
57 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo
,
58 weak_ptr_factory_
.GetWeakPtr(),
64 // MediaTransferProtocolDaemonClient override.
65 virtual void OpenStorage(const std::string
& storage_name
,
66 const std::string
& mode
,
67 const OpenStorageCallback
& callback
,
68 const ErrorCallback
& error_callback
) OVERRIDE
{
69 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kOpenStorage
);
70 dbus::MessageWriter
writer(&method_call
);
71 writer
.AppendString(storage_name
);
72 DCHECK_EQ(mtpd::kReadOnlyMode
, mode
);
73 writer
.AppendString(mtpd::kReadOnlyMode
);
75 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
76 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage
,
77 weak_ptr_factory_
.GetWeakPtr(),
82 // MediaTransferProtocolDaemonClient override.
83 virtual void CloseStorage(const std::string
& handle
,
84 const CloseStorageCallback
& callback
,
85 const ErrorCallback
& error_callback
) OVERRIDE
{
86 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kCloseStorage
);
87 dbus::MessageWriter
writer(&method_call
);
88 writer
.AppendString(handle
);
90 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
91 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage
,
92 weak_ptr_factory_
.GetWeakPtr(),
97 // MediaTransferProtocolDaemonClient override.
98 virtual void ReadDirectoryByPath(
99 const std::string
& handle
,
100 const std::string
& path
,
101 const ReadDirectoryCallback
& callback
,
102 const ErrorCallback
& error_callback
) OVERRIDE
{
103 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
104 mtpd::kReadDirectoryByPath
);
105 dbus::MessageWriter
writer(&method_call
);
106 writer
.AppendString(handle
);
107 writer
.AppendString(path
);
109 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
110 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory
,
111 weak_ptr_factory_
.GetWeakPtr(),
116 // MediaTransferProtocolDaemonClient override.
117 virtual void ReadDirectoryById(
118 const std::string
& handle
,
120 const ReadDirectoryCallback
& callback
,
121 const ErrorCallback
& error_callback
) OVERRIDE
{
122 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
123 mtpd::kReadDirectoryById
);
124 dbus::MessageWriter
writer(&method_call
);
125 writer
.AppendString(handle
);
126 writer
.AppendUint32(file_id
);
128 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
129 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory
,
130 weak_ptr_factory_
.GetWeakPtr(),
135 // MediaTransferProtocolDaemonClient override.
136 virtual void ReadFileChunkByPath(
137 const std::string
& handle
,
138 const std::string
& path
,
140 uint32 bytes_to_read
,
141 const ReadFileCallback
& callback
,
142 const ErrorCallback
& error_callback
) OVERRIDE
{
143 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
144 mtpd::kReadFileChunkByPath
);
145 dbus::MessageWriter
writer(&method_call
);
146 writer
.AppendString(handle
);
147 writer
.AppendString(path
);
148 writer
.AppendUint32(offset
);
149 writer
.AppendUint32(bytes_to_read
);
151 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
152 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile
,
153 weak_ptr_factory_
.GetWeakPtr(),
158 // MediaTransferProtocolDaemonClient override.
159 virtual void ReadFileChunkById(const std::string
& handle
,
162 uint32 bytes_to_read
,
163 const ReadFileCallback
& callback
,
164 const ErrorCallback
& error_callback
) OVERRIDE
{
165 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
166 mtpd::kReadFileChunkById
);
167 dbus::MessageWriter
writer(&method_call
);
168 writer
.AppendString(handle
);
169 writer
.AppendUint32(file_id
);
170 writer
.AppendUint32(offset
);
171 writer
.AppendUint32(bytes_to_read
);
173 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
174 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile
,
175 weak_ptr_factory_
.GetWeakPtr(),
180 // MediaTransferProtocolDaemonClient override.
181 virtual void GetFileInfoByPath(const std::string
& handle
,
182 const std::string
& path
,
183 const GetFileInfoCallback
& callback
,
184 const ErrorCallback
& error_callback
) OVERRIDE
{
185 dbus::MethodCall
method_call(mtpd::kMtpdInterface
,
186 mtpd::kGetFileInfoByPath
);
187 dbus::MessageWriter
writer(&method_call
);
188 writer
.AppendString(handle
);
189 writer
.AppendString(path
);
191 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
192 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo
,
193 weak_ptr_factory_
.GetWeakPtr(),
198 // MediaTransferProtocolDaemonClient override.
199 virtual void GetFileInfoById(const std::string
& handle
,
201 const GetFileInfoCallback
& callback
,
202 const ErrorCallback
& error_callback
) OVERRIDE
{
203 dbus::MethodCall
method_call(mtpd::kMtpdInterface
, mtpd::kGetFileInfoById
);
204 dbus::MessageWriter
writer(&method_call
);
205 writer
.AppendString(handle
);
206 writer
.AppendUint32(file_id
);
208 &method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
209 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo
,
210 weak_ptr_factory_
.GetWeakPtr(),
215 // MediaTransferProtocolDaemonClient override.
216 virtual void ListenForChanges(
217 const MTPStorageEventHandler
& handler
) OVERRIDE
{
218 DCHECK(!listen_for_changes_called_
);
219 listen_for_changes_called_
= true;
221 static const SignalEventTuple kSignalEventTuples
[] = {
222 { mtpd::kMTPStorageAttached
, true },
223 { mtpd::kMTPStorageDetached
, false },
225 const size_t kNumSignalEventTuples
= arraysize(kSignalEventTuples
);
227 for (size_t i
= 0; i
< kNumSignalEventTuples
; ++i
) {
228 proxy_
->ConnectToSignal(
229 mtpd::kMtpdInterface
,
230 kSignalEventTuples
[i
].signal_name
,
231 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal
,
232 weak_ptr_factory_
.GetWeakPtr(),
234 kSignalEventTuples
[i
].is_attach
),
235 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected
,
236 weak_ptr_factory_
.GetWeakPtr()));
241 // A struct to contain a pair of signal name and attachment event type.
242 // Used by SetUpConnections.
243 struct SignalEventTuple
{
244 const char *signal_name
;
248 // Handles the result of EnumerateStorages and calls |callback| or
250 void OnEnumerateStorages(const EnumerateStoragesCallback
& callback
,
251 const ErrorCallback
& error_callback
,
252 dbus::Response
* response
) {
254 error_callback
.Run();
257 dbus::MessageReader
reader(response
);
258 std::vector
<std::string
> storage_names
;
259 if (!reader
.PopArrayOfStrings(&storage_names
)) {
260 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
261 error_callback
.Run();
264 callback
.Run(storage_names
);
267 // Handles the result of GetStorageInfo and calls |callback| or
269 void OnGetStorageInfo(const std::string
& storage_name
,
270 const GetStorageInfoCallback
& callback
,
271 const ErrorCallback
& error_callback
,
272 dbus::Response
* response
) {
274 error_callback
.Run();
278 dbus::MessageReader
reader(response
);
279 MtpStorageInfo protobuf
;
280 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
281 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
282 error_callback
.Run();
285 callback
.Run(protobuf
);
288 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
289 void OnOpenStorage(const OpenStorageCallback
& callback
,
290 const ErrorCallback
& error_callback
,
291 dbus::Response
* response
) {
293 error_callback
.Run();
296 dbus::MessageReader
reader(response
);
298 if (!reader
.PopString(&handle
)) {
299 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
300 error_callback
.Run();
303 callback
.Run(handle
);
306 // Handles the result of CloseStorage and calls |callback| or
308 void OnCloseStorage(const CloseStorageCallback
& callback
,
309 const ErrorCallback
& error_callback
,
310 dbus::Response
* response
) {
312 error_callback
.Run();
318 // Handles the result of ReadDirectoryByPath/Id and calls |callback| or
320 void OnReadDirectory(const ReadDirectoryCallback
& callback
,
321 const ErrorCallback
& error_callback
,
322 dbus::Response
* response
) {
324 error_callback
.Run();
328 std::vector
<MtpFileEntry
> file_entries
;
329 dbus::MessageReader
reader(response
);
330 MtpFileEntries entries_protobuf
;
331 if (!reader
.PopArrayOfBytesAsProto(&entries_protobuf
)) {
332 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
333 error_callback
.Run();
337 for (int i
= 0; i
< entries_protobuf
.file_entries_size(); ++i
)
338 file_entries
.push_back(entries_protobuf
.file_entries(i
));
339 callback
.Run(file_entries
);
342 // Handles the result of ReadFileChunkByPath/Id and calls |callback| or
344 void OnReadFile(const ReadFileCallback
& callback
,
345 const ErrorCallback
& error_callback
,
346 dbus::Response
* response
) {
348 error_callback
.Run();
352 uint8
* data_bytes
= NULL
;
353 size_t data_length
= 0;
354 dbus::MessageReader
reader(response
);
355 if (!reader
.PopArrayOfBytes(&data_bytes
, &data_length
)) {
356 error_callback
.Run();
359 std::string
data(reinterpret_cast<const char*>(data_bytes
), data_length
);
363 // Handles the result of GetFileInfoByPath/Id and calls |callback| or
365 void OnGetFileInfo(const GetFileInfoCallback
& callback
,
366 const ErrorCallback
& error_callback
,
367 dbus::Response
* response
) {
369 error_callback
.Run();
373 dbus::MessageReader
reader(response
);
374 MtpFileEntry protobuf
;
375 if (!reader
.PopArrayOfBytesAsProto(&protobuf
)) {
376 LOG(ERROR
) << kInvalidResponseMsg
<< response
->ToString();
377 error_callback
.Run();
380 callback
.Run(protobuf
);
383 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
384 void OnMTPStorageSignal(MTPStorageEventHandler handler
,
386 dbus::Signal
* signal
) {
387 dbus::MessageReader
reader(signal
);
388 std::string storage_name
;
389 if (!reader
.PopString(&storage_name
)) {
390 LOG(ERROR
) << "Invalid signal: " << signal
->ToString();
393 DCHECK(!storage_name
.empty());
394 handler
.Run(is_attach
, storage_name
);
398 // Handles the result of signal connection setup.
399 void OnSignalConnected(const std::string
& interface
,
400 const std::string
& signal
,
402 LOG_IF(ERROR
, !succeeded
) << "Connect to " << interface
<< " "
403 << signal
<< " failed.";
406 dbus::ObjectProxy
* proxy_
;
408 bool listen_for_changes_called_
;
410 // Note: This should remain the last member so it'll be destroyed and
411 // invalidate its weak pointers before any other members are destroyed.
412 base::WeakPtrFactory
<MediaTransferProtocolDaemonClientImpl
> weak_ptr_factory_
;
414 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl
);
419 ////////////////////////////////////////////////////////////////////////////////
420 // MediaTransferProtocolDaemonClient
422 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
424 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
427 MediaTransferProtocolDaemonClient
* MediaTransferProtocolDaemonClient::Create(
429 return new MediaTransferProtocolDaemonClientImpl(bus
);
432 } // namespace device