Adding Test Fixture for initial test cases for the App Remoting Test Driver. Also...
[chromium-blink-merge.git] / device / media_transfer_protocol / media_transfer_protocol_daemon_client.cc
blob8c2b2d9139e7faa073aae86f07aa8b9514499fae
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"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/memory/weak_ptr.h"
11 #include "dbus/bus.h"
12 #include "dbus/message.h"
13 #include "dbus/object_path.h"
14 #include "dbus/object_proxy.h"
15 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
16 #include "device/media_transfer_protocol/mtp_storage_info.pb.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace device {
21 namespace {
23 const char kInvalidResponseMsg[] = "Invalid Response: ";
24 uint32 kMaxChunkSize = 1024*1024; // D-Bus has message size limits.
26 // The MediaTransferProtocolDaemonClient implementation.
27 class MediaTransferProtocolDaemonClientImpl
28 : public MediaTransferProtocolDaemonClient {
29 public:
30 explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus* bus)
31 : proxy_(bus->GetObjectProxy(
32 mtpd::kMtpdServiceName,
33 dbus::ObjectPath(mtpd::kMtpdServicePath))),
34 listen_for_changes_called_(false),
35 weak_ptr_factory_(this) {
38 // MediaTransferProtocolDaemonClient override.
39 void EnumerateStorages(const EnumerateStoragesCallback& callback,
40 const ErrorCallback& error_callback) override {
41 dbus::MethodCall method_call(mtpd::kMtpdInterface,
42 mtpd::kEnumerateStorages);
43 proxy_->CallMethod(
44 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
45 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorages,
46 weak_ptr_factory_.GetWeakPtr(),
47 callback,
48 error_callback));
51 // MediaTransferProtocolDaemonClient override.
52 void GetStorageInfo(const std::string& storage_name,
53 const GetStorageInfoCallback& callback,
54 const ErrorCallback& error_callback) override {
55 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetStorageInfo);
56 dbus::MessageWriter writer(&method_call);
57 writer.AppendString(storage_name);
58 proxy_->CallMethod(
59 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
60 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo,
61 weak_ptr_factory_.GetWeakPtr(),
62 storage_name,
63 callback,
64 error_callback));
67 // MediaTransferProtocolDaemonClient override.
68 void OpenStorage(const std::string& storage_name,
69 const std::string& mode,
70 const OpenStorageCallback& callback,
71 const ErrorCallback& error_callback) override {
72 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kOpenStorage);
73 dbus::MessageWriter writer(&method_call);
74 writer.AppendString(storage_name);
75 DCHECK(mode == mtpd::kReadOnlyMode || mode == mtpd::kReadWriteMode);
76 writer.AppendString(mode);
77 proxy_->CallMethod(
78 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
79 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage,
80 weak_ptr_factory_.GetWeakPtr(),
81 callback,
82 error_callback));
85 // MediaTransferProtocolDaemonClient override.
86 void CloseStorage(const std::string& handle,
87 const CloseStorageCallback& callback,
88 const ErrorCallback& error_callback) override {
89 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kCloseStorage);
90 dbus::MessageWriter writer(&method_call);
91 writer.AppendString(handle);
92 proxy_->CallMethod(
93 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
94 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage,
95 weak_ptr_factory_.GetWeakPtr(),
96 callback,
97 error_callback));
100 // MediaTransferProtocolDaemonClient override.
101 void ReadDirectoryEntryIds(const std::string& handle,
102 uint32 file_id,
103 const ReadDirectoryEntryIdsCallback& callback,
104 const ErrorCallback& error_callback) override {
105 dbus::MethodCall method_call(mtpd::kMtpdInterface,
106 mtpd::kReadDirectoryEntryIds);
107 dbus::MessageWriter writer(&method_call);
108 writer.AppendString(handle);
109 writer.AppendUint32(file_id);
110 proxy_->CallMethod(
111 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
112 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectoryIds,
113 weak_ptr_factory_.GetWeakPtr(),
114 callback,
115 error_callback));
118 void GetFileInfo(const std::string& handle,
119 const std::vector<uint32>& file_ids,
120 size_t offset,
121 size_t entries_to_read,
122 const GetFileInfoCallback& callback,
123 const ErrorCallback& error_callback) override {
124 if (offset >= file_ids.size()) {
125 error_callback.Run();
126 return;
129 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetFileInfo);
130 dbus::MessageWriter writer(&method_call);
131 writer.AppendString(handle);
133 dbus::MessageWriter array_writer(NULL);
134 writer.OpenArray("u", &array_writer);
136 size_t end_offset = file_ids.size();
137 if (offset <= SIZE_MAX - entries_to_read)
138 end_offset = std::min(end_offset, offset + entries_to_read);
139 for (size_t i = offset; i < end_offset; ++i)
140 array_writer.AppendUint32(file_ids[i]);
142 writer.CloseContainer(&array_writer);
144 proxy_->CallMethod(
145 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
146 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo,
147 weak_ptr_factory_.GetWeakPtr(),
148 callback,
149 error_callback));
152 // MediaTransferProtocolDaemonClient override.
153 void ReadFileChunk(const std::string& handle,
154 uint32 file_id,
155 uint32 offset,
156 uint32 bytes_to_read,
157 const ReadFileCallback& callback,
158 const ErrorCallback& error_callback) override {
159 DCHECK_LE(bytes_to_read, kMaxChunkSize);
160 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kReadFileChunk);
161 dbus::MessageWriter writer(&method_call);
162 writer.AppendString(handle);
163 writer.AppendUint32(file_id);
164 writer.AppendUint32(offset);
165 writer.AppendUint32(bytes_to_read);
166 proxy_->CallMethod(
167 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
168 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
169 weak_ptr_factory_.GetWeakPtr(),
170 callback,
171 error_callback));
174 void RenameObject(const std::string& handle,
175 const uint32 object_id,
176 const std::string& new_name,
177 const RenameObjectCallback& callback,
178 const ErrorCallback& error_callback) override {
179 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kRenameObject);
180 dbus::MessageWriter writer(&method_call);
181 writer.AppendString(handle);
182 writer.AppendUint32(object_id);
183 writer.AppendString(new_name);
184 proxy_->CallMethod(
185 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
186 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnRenameObject,
187 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
190 void CopyFileFromLocal(const std::string& handle,
191 const int source_file_descriptor,
192 const uint32 parent_id,
193 const std::string& file_name,
194 const CopyFileFromLocalCallback& callback,
195 const ErrorCallback& error_callback) override {
196 dbus::FileDescriptor file_descriptor(source_file_descriptor);
197 file_descriptor.CheckValidity();
199 dbus::MethodCall method_call(mtpd::kMtpdInterface,
200 mtpd::kCopyFileFromLocal);
201 dbus::MessageWriter writer(&method_call);
202 writer.AppendString(handle);
203 writer.AppendFileDescriptor(file_descriptor);
204 writer.AppendUint32(parent_id);
205 writer.AppendString(file_name);
206 proxy_->CallMethod(
207 &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
208 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCopyFileFromLocal,
209 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
212 void DeleteObject(const std::string& handle,
213 const uint32 object_id,
214 const DeleteObjectCallback& callback,
215 const ErrorCallback& error_callback) override {
216 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kDeleteObject);
217 dbus::MessageWriter writer(&method_call);
218 writer.AppendString(handle);
219 writer.AppendUint32(object_id);
220 proxy_->CallMethod(
221 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
222 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnDeleteObject,
223 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
226 // MediaTransferProtocolDaemonClient override.
227 void ListenForChanges(const MTPStorageEventHandler& handler) override {
228 DCHECK(!listen_for_changes_called_);
229 listen_for_changes_called_ = true;
231 static const SignalEventTuple kSignalEventTuples[] = {
232 { mtpd::kMTPStorageAttached, true },
233 { mtpd::kMTPStorageDetached, false },
235 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
237 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
238 proxy_->ConnectToSignal(
239 mtpd::kMtpdInterface,
240 kSignalEventTuples[i].signal_name,
241 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal,
242 weak_ptr_factory_.GetWeakPtr(),
243 handler,
244 kSignalEventTuples[i].is_attach),
245 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected,
246 weak_ptr_factory_.GetWeakPtr()));
250 private:
251 // A struct to contain a pair of signal name and attachment event type.
252 // Used by SetUpConnections.
253 struct SignalEventTuple {
254 const char* signal_name;
255 bool is_attach;
258 // Handles the result of EnumerateStorages and calls |callback| or
259 // |error_callback|.
260 void OnEnumerateStorages(const EnumerateStoragesCallback& callback,
261 const ErrorCallback& error_callback,
262 dbus::Response* response) {
263 if (!response) {
264 error_callback.Run();
265 return;
267 dbus::MessageReader reader(response);
268 std::vector<std::string> storage_names;
269 if (!reader.PopArrayOfStrings(&storage_names)) {
270 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
271 error_callback.Run();
272 return;
274 callback.Run(storage_names);
277 // Handles the result of GetStorageInfo and calls |callback| or
278 // |error_callback|.
279 void OnGetStorageInfo(const std::string& storage_name,
280 const GetStorageInfoCallback& callback,
281 const ErrorCallback& error_callback,
282 dbus::Response* response) {
283 if (!response) {
284 error_callback.Run();
285 return;
288 dbus::MessageReader reader(response);
289 MtpStorageInfo protobuf;
290 if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
291 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
292 error_callback.Run();
293 return;
295 callback.Run(protobuf);
298 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
299 void OnOpenStorage(const OpenStorageCallback& callback,
300 const ErrorCallback& error_callback,
301 dbus::Response* response) {
302 if (!response) {
303 error_callback.Run();
304 return;
306 dbus::MessageReader reader(response);
307 std::string handle;
308 if (!reader.PopString(&handle)) {
309 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
310 error_callback.Run();
311 return;
313 callback.Run(handle);
316 // Handles the result of CloseStorage and calls |callback| or
317 // |error_callback|.
318 void OnCloseStorage(const CloseStorageCallback& callback,
319 const ErrorCallback& error_callback,
320 dbus::Response* response) {
321 if (!response) {
322 error_callback.Run();
323 return;
325 callback.Run();
328 // Handles the result of ReadDirectoryEntryIds and calls |callback| or
329 // |error_callback|.
330 void OnReadDirectoryIds(const ReadDirectoryEntryIdsCallback& callback,
331 const ErrorCallback& error_callback,
332 dbus::Response* response) {
333 if (!response) {
334 error_callback.Run();
335 return;
338 std::vector<uint32> file_ids;
339 dbus::MessageReader reader(response);
340 dbus::MessageReader array_reader(NULL);
341 if (!reader.PopArray(&array_reader) || reader.HasMoreData()) {
342 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
343 error_callback.Run();
344 return;
347 while (array_reader.HasMoreData()) {
348 uint32 file_id;
349 if (array_reader.PopUint32(&file_id)) {
350 file_ids.push_back(file_id);
351 } else {
352 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
353 error_callback.Run();
354 return;
357 callback.Run(file_ids);
360 // Handles the result of GetFileInfo and calls |callback| or |error_callback|.
361 void OnGetFileInfo(const GetFileInfoCallback& callback,
362 const ErrorCallback& error_callback,
363 dbus::Response* response) {
364 if (!response) {
365 error_callback.Run();
366 return;
369 std::vector<MtpFileEntry> file_entries;
370 dbus::MessageReader reader(response);
371 MtpFileEntries entries_protobuf;
372 if (!reader.PopArrayOfBytesAsProto(&entries_protobuf)) {
373 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
374 error_callback.Run();
375 return;
378 for (int i = 0; i < entries_protobuf.file_entries_size(); ++i)
379 file_entries.push_back(entries_protobuf.file_entries(i));
380 callback.Run(file_entries);
383 // Handles the result of ReadFileChunk and calls |callback| or
384 // |error_callback|.
385 void OnReadFile(const ReadFileCallback& callback,
386 const ErrorCallback& error_callback,
387 dbus::Response* response) {
388 if (!response) {
389 error_callback.Run();
390 return;
393 const uint8* data_bytes = NULL;
394 size_t data_length = 0;
395 dbus::MessageReader reader(response);
396 if (!reader.PopArrayOfBytes(&data_bytes, &data_length)) {
397 error_callback.Run();
398 return;
400 std::string data(reinterpret_cast<const char*>(data_bytes), data_length);
401 callback.Run(data);
404 void OnRenameObject(const RenameObjectCallback& callback,
405 const ErrorCallback& error_callback,
406 dbus::Response* response) {
407 if (!response) {
408 error_callback.Run();
409 return;
412 callback.Run();
415 void OnCopyFileFromLocal(const CopyFileFromLocalCallback& callback,
416 const ErrorCallback& error_callback,
417 dbus::Response* response) {
418 if (!response) {
419 error_callback.Run();
420 return;
423 callback.Run();
426 void OnDeleteObject(const DeleteObjectCallback& callback,
427 const ErrorCallback& error_callback,
428 dbus::Response* response) {
429 if (!response) {
430 error_callback.Run();
431 return;
434 callback.Run();
437 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
438 void OnMTPStorageSignal(MTPStorageEventHandler handler,
439 bool is_attach,
440 dbus::Signal* signal) {
441 dbus::MessageReader reader(signal);
442 std::string storage_name;
443 if (!reader.PopString(&storage_name)) {
444 LOG(ERROR) << "Invalid signal: " << signal->ToString();
445 return;
447 DCHECK(!storage_name.empty());
448 handler.Run(is_attach, storage_name);
452 // Handles the result of signal connection setup.
453 void OnSignalConnected(const std::string& interface,
454 const std::string& signal,
455 bool succeeded) {
456 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
457 << signal << " failed.";
460 dbus::ObjectProxy* proxy_;
462 bool listen_for_changes_called_;
464 // Note: This should remain the last member so it'll be destroyed and
465 // invalidate its weak pointers before any other members are destroyed.
466 base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_;
468 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl);
471 } // namespace
473 ////////////////////////////////////////////////////////////////////////////////
474 // MediaTransferProtocolDaemonClient
476 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
478 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
480 // static
481 MediaTransferProtocolDaemonClient* MediaTransferProtocolDaemonClient::Create(
482 dbus::Bus* bus) {
483 return new MediaTransferProtocolDaemonClientImpl(bus);
486 } // namespace device