Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / device / media_transfer_protocol / media_transfer_protocol_daemon_client.cc
blob5639169060180afc8de56657ffd83fb30188529d
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 virtual 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 virtual 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 virtual 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_EQ(mtpd::kReadOnlyMode, mode);
76 writer.AppendString(mtpd::kReadOnlyMode);
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 virtual 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 virtual void ReadDirectoryEntryIds(
102 const std::string& handle,
103 uint32 file_id,
104 const ReadDirectoryEntryIdsCallback& callback,
105 const ErrorCallback& error_callback) OVERRIDE {
106 dbus::MethodCall method_call(mtpd::kMtpdInterface,
107 mtpd::kReadDirectoryEntryIds);
108 dbus::MessageWriter writer(&method_call);
109 writer.AppendString(handle);
110 writer.AppendUint32(file_id);
111 proxy_->CallMethod(
112 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
113 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectoryIds,
114 weak_ptr_factory_.GetWeakPtr(),
115 callback,
116 error_callback));
119 virtual void GetFileInfo(const std::string& handle,
120 const std::vector<uint32>& file_ids,
121 size_t offset,
122 size_t entries_to_read,
123 const GetFileInfoCallback& callback,
124 const ErrorCallback& error_callback) OVERRIDE {
125 if (offset >= file_ids.size()) {
126 error_callback.Run();
127 return;
130 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetFileInfo);
131 dbus::MessageWriter writer(&method_call);
132 writer.AppendString(handle);
134 dbus::MessageWriter array_writer(NULL);
135 writer.OpenArray("u", &array_writer);
137 size_t end_offset = file_ids.size();
138 if (offset <= SIZE_MAX - entries_to_read)
139 end_offset = std::min(end_offset, offset + entries_to_read);
140 for (size_t i = offset; i < end_offset; ++i)
141 array_writer.AppendUint32(file_ids[i]);
143 writer.CloseContainer(&array_writer);
145 proxy_->CallMethod(
146 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
147 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo,
148 weak_ptr_factory_.GetWeakPtr(),
149 callback,
150 error_callback));
153 // MediaTransferProtocolDaemonClient override.
154 virtual void ReadFileChunk(const std::string& handle,
155 uint32 file_id,
156 uint32 offset,
157 uint32 bytes_to_read,
158 const ReadFileCallback& callback,
159 const ErrorCallback& error_callback) OVERRIDE {
160 DCHECK_LE(bytes_to_read, kMaxChunkSize);
161 dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kReadFileChunk);
162 dbus::MessageWriter writer(&method_call);
163 writer.AppendString(handle);
164 writer.AppendUint32(file_id);
165 writer.AppendUint32(offset);
166 writer.AppendUint32(bytes_to_read);
167 proxy_->CallMethod(
168 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
169 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
170 weak_ptr_factory_.GetWeakPtr(),
171 callback,
172 error_callback));
175 // MediaTransferProtocolDaemonClient override.
176 virtual void ListenForChanges(
177 const MTPStorageEventHandler& handler) OVERRIDE {
178 DCHECK(!listen_for_changes_called_);
179 listen_for_changes_called_ = true;
181 static const SignalEventTuple kSignalEventTuples[] = {
182 { mtpd::kMTPStorageAttached, true },
183 { mtpd::kMTPStorageDetached, false },
185 const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
187 for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
188 proxy_->ConnectToSignal(
189 mtpd::kMtpdInterface,
190 kSignalEventTuples[i].signal_name,
191 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal,
192 weak_ptr_factory_.GetWeakPtr(),
193 handler,
194 kSignalEventTuples[i].is_attach),
195 base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected,
196 weak_ptr_factory_.GetWeakPtr()));
200 private:
201 // A struct to contain a pair of signal name and attachment event type.
202 // Used by SetUpConnections.
203 struct SignalEventTuple {
204 const char* signal_name;
205 bool is_attach;
208 // Handles the result of EnumerateStorages and calls |callback| or
209 // |error_callback|.
210 void OnEnumerateStorages(const EnumerateStoragesCallback& callback,
211 const ErrorCallback& error_callback,
212 dbus::Response* response) {
213 if (!response) {
214 error_callback.Run();
215 return;
217 dbus::MessageReader reader(response);
218 std::vector<std::string> storage_names;
219 if (!reader.PopArrayOfStrings(&storage_names)) {
220 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
221 error_callback.Run();
222 return;
224 callback.Run(storage_names);
227 // Handles the result of GetStorageInfo and calls |callback| or
228 // |error_callback|.
229 void OnGetStorageInfo(const std::string& storage_name,
230 const GetStorageInfoCallback& callback,
231 const ErrorCallback& error_callback,
232 dbus::Response* response) {
233 if (!response) {
234 error_callback.Run();
235 return;
238 dbus::MessageReader reader(response);
239 MtpStorageInfo protobuf;
240 if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
241 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
242 error_callback.Run();
243 return;
245 callback.Run(protobuf);
248 // Handles the result of OpenStorage and calls |callback| or |error_callback|.
249 void OnOpenStorage(const OpenStorageCallback& callback,
250 const ErrorCallback& error_callback,
251 dbus::Response* response) {
252 if (!response) {
253 error_callback.Run();
254 return;
256 dbus::MessageReader reader(response);
257 std::string handle;
258 if (!reader.PopString(&handle)) {
259 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
260 error_callback.Run();
261 return;
263 callback.Run(handle);
266 // Handles the result of CloseStorage and calls |callback| or
267 // |error_callback|.
268 void OnCloseStorage(const CloseStorageCallback& callback,
269 const ErrorCallback& error_callback,
270 dbus::Response* response) {
271 if (!response) {
272 error_callback.Run();
273 return;
275 callback.Run();
278 // Handles the result of ReadDirectoryEntryIds and calls |callback| or
279 // |error_callback|.
280 void OnReadDirectoryIds(const ReadDirectoryEntryIdsCallback& callback,
281 const ErrorCallback& error_callback,
282 dbus::Response* response) {
283 if (!response) {
284 error_callback.Run();
285 return;
288 std::vector<uint32> file_ids;
289 dbus::MessageReader reader(response);
290 dbus::MessageReader array_reader(NULL);
291 if (!reader.PopArray(&array_reader) || reader.HasMoreData()) {
292 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
293 error_callback.Run();
294 return;
297 while (array_reader.HasMoreData()) {
298 uint32 file_id;
299 if (array_reader.PopUint32(&file_id)) {
300 file_ids.push_back(file_id);
301 } else {
302 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
303 error_callback.Run();
304 return;
307 callback.Run(file_ids);
310 // Handles the result of GetFileInfo and calls |callback| or |error_callback|.
311 void OnGetFileInfo(const GetFileInfoCallback& callback,
312 const ErrorCallback& error_callback,
313 dbus::Response* response) {
314 if (!response) {
315 error_callback.Run();
316 return;
319 std::vector<MtpFileEntry> file_entries;
320 dbus::MessageReader reader(response);
321 MtpFileEntries entries_protobuf;
322 if (!reader.PopArrayOfBytesAsProto(&entries_protobuf)) {
323 LOG(ERROR) << kInvalidResponseMsg << response->ToString();
324 error_callback.Run();
325 return;
328 for (int i = 0; i < entries_protobuf.file_entries_size(); ++i)
329 file_entries.push_back(entries_protobuf.file_entries(i));
330 callback.Run(file_entries);
333 // Handles the result of ReadFileChunk and calls |callback| or
334 // |error_callback|.
335 void OnReadFile(const ReadFileCallback& callback,
336 const ErrorCallback& error_callback,
337 dbus::Response* response) {
338 if (!response) {
339 error_callback.Run();
340 return;
343 const uint8* data_bytes = NULL;
344 size_t data_length = 0;
345 dbus::MessageReader reader(response);
346 if (!reader.PopArrayOfBytes(&data_bytes, &data_length)) {
347 error_callback.Run();
348 return;
350 std::string data(reinterpret_cast<const char*>(data_bytes), data_length);
351 callback.Run(data);
354 // Handles MTPStorageAttached/Dettached signals and calls |handler|.
355 void OnMTPStorageSignal(MTPStorageEventHandler handler,
356 bool is_attach,
357 dbus::Signal* signal) {
358 dbus::MessageReader reader(signal);
359 std::string storage_name;
360 if (!reader.PopString(&storage_name)) {
361 LOG(ERROR) << "Invalid signal: " << signal->ToString();
362 return;
364 DCHECK(!storage_name.empty());
365 handler.Run(is_attach, storage_name);
369 // Handles the result of signal connection setup.
370 void OnSignalConnected(const std::string& interface,
371 const std::string& signal,
372 bool succeeded) {
373 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
374 << signal << " failed.";
377 dbus::ObjectProxy* proxy_;
379 bool listen_for_changes_called_;
381 // Note: This should remain the last member so it'll be destroyed and
382 // invalidate its weak pointers before any other members are destroyed.
383 base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_;
385 DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl);
388 } // namespace
390 ////////////////////////////////////////////////////////////////////////////////
391 // MediaTransferProtocolDaemonClient
393 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
395 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
397 // static
398 MediaTransferProtocolDaemonClient* MediaTransferProtocolDaemonClient::Create(
399 dbus::Bus* bus) {
400 return new MediaTransferProtocolDaemonClientImpl(bus);
403 } // namespace device