diff options
Diffstat (limited to 'device')
-rw-r--r-- | device/device.gyp | 49 | ||||
-rw-r--r-- | device/media_transfer_protocol/DEPS | 8 | ||||
-rw-r--r-- | device/media_transfer_protocol/OWNERS | 2 | ||||
-rw-r--r-- | device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc | 489 | ||||
-rw-r--r-- | device/media_transfer_protocol/media_transfer_protocol_daemon_client.h | 180 | ||||
-rw-r--r-- | device/media_transfer_protocol/media_transfer_protocol_manager.cc | 453 | ||||
-rw-r--r-- | device/media_transfer_protocol/media_transfer_protocol_manager.h | 143 |
7 files changed, 1324 insertions, 0 deletions
diff --git a/device/device.gyp b/device/device.gyp index 25db3cb..c8e6a50 100644 --- a/device/device.gyp +++ b/device/device.gyp @@ -151,4 +151,53 @@ ], }, ], + 'conditions': [ + ['OS=="linux"', { + 'targets': [ + { + # Protobuf compiler / generator for the MtpFileEntry and + # MtpFileEntries protocol buffers. + 'target_name': 'mtp_file_entry_proto', + 'type': 'static_library', + 'sources': [ + '../third_party/cros_system_api/dbus/mtp_file_entry.proto', + ], + 'variables': { + 'proto_in_dir': '../third_party/cros_system_api/dbus', + 'proto_out_dir': 'device/media_transfer_protocol', + }, + 'includes': ['../build/protoc.gypi'], + }, + { + # Protobuf compiler / generator for the MtpStorageInfo protocol + # buffer. + 'target_name': 'mtp_storage_info_proto', + 'type': 'static_library', + 'sources': [ + '../third_party/cros_system_api/dbus/mtp_storage_info.proto', + ], + 'variables': { + 'proto_in_dir': '../third_party/cros_system_api/dbus', + 'proto_out_dir': 'device/media_transfer_protocol', + }, + 'includes': ['../build/protoc.gypi'], + }, + { + 'target_name': 'device_media_transfer_protocol', + 'type': 'static_library', + 'dependencies': [ + '../build/linux/system.gyp:dbus', + 'mtp_file_entry_proto', + 'mtp_storage_info_proto', + ], + 'sources': [ + 'media_transfer_protocol/media_transfer_protocol_daemon_client.cc', + 'media_transfer_protocol/media_transfer_protocol_daemon_client.h', + 'media_transfer_protocol/media_transfer_protocol_manager.cc', + 'media_transfer_protocol/media_transfer_protocol_manager.h', + ], + }, + ], + }], + ], } diff --git a/device/media_transfer_protocol/DEPS b/device/media_transfer_protocol/DEPS new file mode 100644 index 0000000..e461e37 --- /dev/null +++ b/device/media_transfer_protocol/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + # The media transfer protocol daemon uses D-Bus. + "+dbus", + "+chrome/common/chrome_switches.h", + "+chromeos/dbus", + "+content/public/browser/browser_thread.h", + "+third_party/cros_system_api/dbus", +] diff --git a/device/media_transfer_protocol/OWNERS b/device/media_transfer_protocol/OWNERS new file mode 100644 index 0000000..8cada85 --- /dev/null +++ b/device/media_transfer_protocol/OWNERS @@ -0,0 +1,2 @@ +satorux@chromium.org +thestig@chromium.org diff --git a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc new file mode 100644 index 0000000..52e8e63 --- /dev/null +++ b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.cc @@ -0,0 +1,489 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "device/media_transfer_protocol/mtp_file_entry.pb.h" +#include "device/media_transfer_protocol/mtp_storage_info.pb.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace device { + +namespace { + +const char kInvalidResponseMsg[] = "Invalid Response: "; + +// The MediaTransferProtocolDaemonClient implementation. +class MediaTransferProtocolDaemonClientImpl + : public MediaTransferProtocolDaemonClient { + public: + explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + mtpd::kMtpdServiceName, + dbus::ObjectPath(mtpd::kMtpdServicePath))), + weak_ptr_factory_(this) { + } + + // MediaTransferProtocolDaemonClient override. + virtual void EnumerateStorages(const EnumerateStoragesCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kEnumerateStorages); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorages, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void GetStorageInfo(const std::string& storage_name, + const GetStorageInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetStorageInfo); + dbus::MessageWriter writer(&method_call); + writer.AppendString(storage_name); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo, + weak_ptr_factory_.GetWeakPtr(), + storage_name, + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void OpenStorage(const std::string& storage_name, + const std::string& mode, + const OpenStorageCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kOpenStorage); + dbus::MessageWriter writer(&method_call); + writer.AppendString(storage_name); + DCHECK_EQ(mtpd::kReadOnlyMode, mode); + writer.AppendString(mtpd::kReadOnlyMode); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void CloseStorage(const std::string& handle, + const CloseStorageCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kCloseStorage); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void ReadDirectoryByPath( + const std::string& handle, + const std::string& path, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kReadDirectoryByPath); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendString(path); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void ReadDirectoryById( + const std::string& handle, + uint32 file_id, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kReadDirectoryById); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendUint32(file_id); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void ReadFileChunkByPath( + const std::string& handle, + const std::string& path, + uint32 offset, + uint32 bytes_to_read, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kReadFileChunkByPath); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendString(path); + writer.AppendUint32(offset); + writer.AppendUint32(bytes_to_read); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void ReadFileChunkById(const std::string& handle, + uint32 file_id, + uint32 offset, + uint32 bytes_to_read, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kReadFileChunkById); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendUint32(file_id); + writer.AppendUint32(offset); + writer.AppendUint32(bytes_to_read); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void GetFileInfoByPath(const std::string& handle, + const std::string& path, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, + mtpd::kGetFileInfoByPath); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendString(path); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void GetFileInfoById(const std::string& handle, + uint32 file_id, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetFileInfoById); + dbus::MessageWriter writer(&method_call); + writer.AppendString(handle); + writer.AppendUint32(file_id); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // MediaTransferProtocolDaemonClient override. + virtual void SetUpConnections( + const MTPStorageEventHandler& handler) OVERRIDE { + static const SignalEventTuple kSignalEventTuples[] = { + { mtpd::kMTPStorageAttached, true }, + { mtpd::kMTPStorageDetached, false }, + }; + const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples); + + for (size_t i = 0; i < kNumSignalEventTuples; ++i) { + proxy_->ConnectToSignal( + mtpd::kMtpdInterface, + kSignalEventTuples[i].signal_name, + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal, + weak_ptr_factory_.GetWeakPtr(), + handler, + kSignalEventTuples[i].is_attach), + base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + } + + private: + // A struct to contain a pair of signal name and attachment event type. + // Used by SetUpConnections. + struct SignalEventTuple { + const char *signal_name; + bool is_attach; + }; + + // Handles the result of EnumerateStorages and calls |callback| or + // |error_callback|. + void OnEnumerateStorages(const EnumerateStoragesCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + dbus::MessageReader reader(response); + std::vector<std::string> storage_names; + if (!reader.PopArrayOfStrings(&storage_names)) { + LOG(ERROR) << kInvalidResponseMsg << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(storage_names); + } + + // Handles the result of GetStorageInfo and calls |callback| or + // |error_callback|. + void OnGetStorageInfo(const std::string& storage_name, + const GetStorageInfoCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + + dbus::MessageReader reader(response); + MtpStorageInfo protobuf; + if (!reader.PopArrayOfBytesAsProto(&protobuf)) { + LOG(ERROR) << kInvalidResponseMsg << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(protobuf); + } + + // Handles the result of OpenStorage and calls |callback| or |error_callback|. + void OnOpenStorage(const OpenStorageCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + dbus::MessageReader reader(response); + std::string handle; + if (!reader.PopString(&handle)) { + LOG(ERROR) << kInvalidResponseMsg << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(handle); + } + + // Handles the result of CloseStorage and calls |callback| or + // |error_callback|. + void OnCloseStorage(const CloseStorageCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + callback.Run(); + } + + // Handles the result of ReadDirectoryByPath/Id and calls |callback| or + // |error_callback|. + void OnReadDirectory(const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + + std::vector<MtpFileEntry> file_entries; + dbus::MessageReader reader(response); + MtpFileEntries entries_protobuf; + if (!reader.PopArrayOfBytesAsProto(&entries_protobuf)) { + LOG(ERROR) << kInvalidResponseMsg << response->ToString(); + error_callback.Run(); + return; + } + + for (int i = 0; i < entries_protobuf.file_entries_size(); ++i) + file_entries.push_back(entries_protobuf.file_entries(i)); + callback.Run(file_entries); + } + + // Handles the result of ReadFileChunkByPath/Id and calls |callback| or + // |error_callback|. + void OnReadFile(const ReadFileCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + + uint8* data_bytes = NULL; + size_t data_length = 0; + dbus::MessageReader reader(response); + if (!reader.PopArrayOfBytes(&data_bytes, &data_length)) { + error_callback.Run(); + return; + } + std::string data(reinterpret_cast<const char*>(data_bytes), data_length); + callback.Run(data); + } + + // Handles the result of GetFileInfoByPath/Id and calls |callback| or + // |error_callback|. + void OnGetFileInfo(const GetFileInfoCallback& callback, + const ErrorCallback& error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + + dbus::MessageReader reader(response); + MtpFileEntry protobuf; + if (!reader.PopArrayOfBytesAsProto(&protobuf)) { + LOG(ERROR) << kInvalidResponseMsg << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(protobuf); + } + + // Handles MTPStorageAttached/Dettached signals and calls |handler|. + void OnMTPStorageSignal(MTPStorageEventHandler handler, + bool is_attach, + dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string storage_name; + if (!reader.PopString(&storage_name)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + DCHECK(!storage_name.empty()); + handler.Run(is_attach, storage_name); + } + + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool succeeded) { + LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " + << signal << " failed."; + } + + dbus::ObjectProxy* proxy_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl); +}; + +// A stub implementaion of MediaTransferProtocolDaemonClient. +class MediaTransferProtocolDaemonClientStubImpl + : public MediaTransferProtocolDaemonClient { + public: + MediaTransferProtocolDaemonClientStubImpl() {} + virtual ~MediaTransferProtocolDaemonClientStubImpl() {} + + virtual void EnumerateStorages( + const EnumerateStoragesCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void GetStorageInfo( + const std::string& storage_name, + const GetStorageInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void OpenStorage(const std::string& storage_name, + const std::string& mode, + const OpenStorageCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void CloseStorage(const std::string& handle, + const CloseStorageCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void ReadDirectoryByPath( + const std::string& handle, + const std::string& path, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void ReadDirectoryById( + const std::string& handle, + uint32 file_id, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void ReadFileChunkByPath( + const std::string& handle, + const std::string& path, + uint32 offset, + uint32 length, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void ReadFileChunkById( + const std::string& handle, + uint32 file_id, + uint32 offset, + uint32 length, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void GetFileInfoByPath( + const std::string& handle, + const std::string& path, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void GetFileInfoById(const std::string& handle, + uint32 file_id, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) OVERRIDE {} + virtual void SetUpConnections( + const MTPStorageEventHandler& handler) OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientStubImpl); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// MediaTransferProtocolDaemonClient + +MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {} + +MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {} + +// static +MediaTransferProtocolDaemonClient* +MediaTransferProtocolDaemonClient::Create(dbus::Bus* bus, bool is_stub) { + if (is_stub) + return new MediaTransferProtocolDaemonClientStubImpl(); + return new MediaTransferProtocolDaemonClientImpl(bus); +} + +} // namespace device diff --git a/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h new file mode 100644 index 0000000..bba9794 --- /dev/null +++ b/device/media_transfer_protocol/media_transfer_protocol_daemon_client.h @@ -0,0 +1,180 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Client code to talk to the Media Transfer Protocol daemon. The MTP daemon is +// responsible for communicating with PTP / MTP capable devices like cameras +// and smartphones. + +#ifndef DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_DAEMON_CLIENT_H_ +#define DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_DAEMON_CLIENT_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "build/build_config.h" + +#if !defined(OS_LINUX) +#error "Only used on Linux and ChromeOS" +#endif + +class MtpFileEntry; +class MtpStorageInfo; + +namespace dbus { +class Bus; +} + +namespace device { + +// A class to make the actual DBus calls for mtpd service. +// This class only makes calls, result/error handling should be done +// by callbacks. +class MediaTransferProtocolDaemonClient { + public: + // A callback to be called when DBus method call fails. + typedef base::Callback<void()> ErrorCallback; + + // A callback to handle the result of EnumerateAutoMountableDevices. + // The argument is the enumerated storage names. + typedef base::Callback<void(const std::vector<std::string>& storage_names) + > EnumerateStoragesCallback; + + // A callback to handle the result of GetStorageInfo. + // The argument is the information about the specified storage. + typedef base::Callback<void(const MtpStorageInfo& storage_info) + > GetStorageInfoCallback; + + // A callback to handle the result of OpenStorage. + // The argument is the returned handle. + typedef base::Callback<void(const std::string& handle)> OpenStorageCallback; + + // A callback to handle the result of CloseStorage. + typedef base::Callback<void()> CloseStorageCallback; + + // A callback to handle the result of ReadDirectoryByPath/Id. + // The argument is a vector of file entries. + typedef base::Callback<void(const std::vector<MtpFileEntry>& file_entries) + > ReadDirectoryCallback; + + // A callback to handle the result of ReadFileChunkByPath/Id. + // The argument is a string containing the file data. + typedef base::Callback<void(const std::string& data)> ReadFileCallback; + + // A callback to handle the result of GetFileInfoByPath/Id. + // The argument is a file entry. + typedef base::Callback<void(const MtpFileEntry& file_entry) + > GetFileInfoCallback; + + // A callback to handle storage attach/detach events. + // The first argument is true for attach, false for detach. + // The second argument is the storage name. + typedef base::Callback<void(bool is_attach, + const std::string& storage_name) + > MTPStorageEventHandler; + + virtual ~MediaTransferProtocolDaemonClient(); + + // Calls EnumerateStorages method. |callback| is called after the + // method call succeeds, otherwise, |error_callback| is called. + virtual void EnumerateStorages( + const EnumerateStoragesCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls GetStorageInfo method. |callback| is called after the method call + // succeeds, otherwise, |error_callback| is called. + virtual void GetStorageInfo(const std::string& storage_name, + const GetStorageInfoCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls OpenStorage method. |callback| is called after the method call + // succeeds, otherwise, |error_callback| is called. + // OpenStorage returns a handle in |callback|. + virtual void OpenStorage(const std::string& storage_name, + const std::string& mode, + const OpenStorageCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls CloseStorage method. |callback| is called after the method call + // succeeds, otherwise, |error_callback| is called. + // |handle| comes from a OpenStorageCallback. + virtual void CloseStorage(const std::string& handle, + const CloseStorageCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls ReadDirectoryByPath method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + virtual void ReadDirectoryByPath(const std::string& handle, + const std::string& path, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls ReadDirectoryById method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + // |file_id| is a MTP-device specific id for a file. + virtual void ReadDirectoryById(const std::string& handle, + uint32 file_id, + const ReadDirectoryCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls ReadFileChunkByPath method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + // |bytes_to_read| cannot exceed 1 MiB. + virtual void ReadFileChunkByPath(const std::string& handle, + const std::string& path, + uint32 offset, + uint32 bytes_to_read, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) = 0; + + // TODO(thestig) Remove this in the near future if we don't see anyone using + // it. + // Calls ReadFilePathById method. |callback| is called after the method call + // succeeds, otherwise, |error_callback| is called. + // |file_id| is a MTP-device specific id for a file. + // |bytes_to_read| cannot exceed 1 MiB. + virtual void ReadFileChunkById(const std::string& handle, + uint32 file_id, + uint32 offset, + uint32 bytes_to_read, + const ReadFileCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls GetFileInfoByPath method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + virtual void GetFileInfoByPath(const std::string& handle, + const std::string& path, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Calls GetFileInfoById method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + // |file_id| is a MTP-device specific id for a file. + virtual void GetFileInfoById(const std::string& handle, + uint32 file_id, + const GetFileInfoCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Registers given callback for events. + // |storage_event_handler| is called when a mtp storage attach or detach + // signal is received. + virtual void SetUpConnections(const MTPStorageEventHandler& handler) = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, set |is_stub| to false. + static MediaTransferProtocolDaemonClient* Create(dbus::Bus* bus, + bool is_stub); + + protected: + // Create() should be used instead. + MediaTransferProtocolDaemonClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClient); +}; + +} // namespace device + +#endif // DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_DAEMON_CLIENT_H_ diff --git a/device/media_transfer_protocol/media_transfer_protocol_manager.cc b/device/media_transfer_protocol/media_transfer_protocol_manager.cc new file mode 100644 index 0000000..dba7d18 --- /dev/null +++ b/device/media_transfer_protocol/media_transfer_protocol_manager.cc @@ -0,0 +1,453 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/media_transfer_protocol/media_transfer_protocol_manager.h" + +#include <map> +#include <queue> +#include <set> +#include <utility> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/stl_util.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_thread.h" +#include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h" +#include "device/media_transfer_protocol/mtp_file_entry.pb.h" +#include "device/media_transfer_protocol/mtp_storage_info.pb.h" + +#if defined(OS_CHROMEOS) +#include "chromeos/dbus/dbus_thread_manager.h" +#else +#include "dbus/bus.h" +#endif + +using content::BrowserThread; + +namespace device { + +namespace { + +MediaTransferProtocolManager* g_media_transfer_protocol_manager = NULL; + +// The MediaTransferProtocolManager implementation. +class MediaTransferProtocolManagerImpl : public MediaTransferProtocolManager { + public: + MediaTransferProtocolManagerImpl() : weak_ptr_factory_(this) { + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) + return; + + dbus::Bus* bus = NULL; +#if defined(OS_CHROMEOS) + chromeos::DBusThreadManager* dbus_thread_manager = + chromeos::DBusThreadManager::Get(); + bus = dbus_thread_manager->GetSystemBus(); + if (!bus) + return; +#else + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + options.connection_type = dbus::Bus::PRIVATE; + options.dbus_thread_message_loop_proxy = + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE); + session_bus_ = new dbus::Bus(options); + bus = session_bus_.get(); +#endif + + DCHECK(bus); + mtp_client_.reset( + MediaTransferProtocolDaemonClient::Create(bus, false /* not stub */)); + + // Set up signals and start initializing |storage_info_map_|. + mtp_client_->SetUpConnections( + base::Bind(&MediaTransferProtocolManagerImpl::OnStorageChanged, + weak_ptr_factory_.GetWeakPtr())); + mtp_client_->EnumerateStorages( + base::Bind(&MediaTransferProtocolManagerImpl::OnEnumerateStorages, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&base::DoNothing)); + } + + virtual ~MediaTransferProtocolManagerImpl() { + } + + // MediaTransferProtocolManager override. + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + // MediaTransferProtocolManager override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + // MediaTransferProtocolManager override. + const std::vector<std::string> GetStorages() const OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::vector<std::string> storages; + for (StorageInfoMap::const_iterator it = storage_info_map_.begin(); + it != storage_info_map_.end(); + ++it) { + storages.push_back(it->first); + } + return storages; + } + + // MediaTransferProtocolManager override. + virtual const MtpStorageInfo* GetStorageInfo( + const std::string& storage_name) const OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + StorageInfoMap::const_iterator it = storage_info_map_.find(storage_name); + if (it == storage_info_map_.end()) + return NULL; + return &it->second; + } + + // MediaTransferProtocolManager override. + virtual void OpenStorage(const std::string& storage_name, + const std::string& mode, + const OpenStorageCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(storage_info_map_, storage_name)) { + callback.Run("", true); + return; + } + open_storage_callbacks_.push(callback); + mtp_client_->OpenStorage( + storage_name, + mode, + base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorage, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnOpenStorageError, + weak_ptr_factory_.GetWeakPtr())); + } + + // MediaTransferProtocolManager override. + virtual void CloseStorage(const std::string& storage_handle, + const CloseStorageCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(true); + return; + } + close_storage_callbacks_.push(std::make_pair(callback, storage_handle)); + mtp_client_->CloseStorage( + storage_handle, + base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorage, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnCloseStorageError, + weak_ptr_factory_.GetWeakPtr())); + } + + // MediaTransferProtocolManager override. + virtual void ReadDirectoryByPath( + const std::string& storage_handle, + const std::string& path, + const ReadDirectoryCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(std::vector<MtpFileEntry>(), true); + return; + } + read_directory_callbacks_.push(callback); + mtp_client_->ReadDirectoryByPath( + storage_handle, + path, + base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError, + weak_ptr_factory_.GetWeakPtr())); + } + + // MediaTransferProtocolManager override. + virtual void ReadDirectoryById( + const std::string& storage_handle, + uint32 file_id, + const ReadDirectoryCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(std::vector<MtpFileEntry>(), true); + return; + } + read_directory_callbacks_.push(callback); + mtp_client_->ReadDirectoryById( + storage_handle, + file_id, + base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectory, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnReadDirectoryError, + weak_ptr_factory_.GetWeakPtr())); + } + + // MediaTransferProtocolManager override. + virtual void ReadFileChunkByPath(const std::string& storage_handle, + const std::string& path, + uint32 offset, + uint32 count, + const ReadFileCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(std::string(), true); + return; + } + read_file_callbacks_.push(callback); + mtp_client_->ReadFileChunkByPath( + storage_handle, path, offset, count, + base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError, + weak_ptr_factory_.GetWeakPtr())); + } + + // MediaTransferProtocolManager override. + virtual void ReadFileChunkById(const std::string& storage_handle, + uint32 file_id, + uint32 offset, + uint32 count, + const ReadFileCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(std::string(), true); + return; + } + read_file_callbacks_.push(callback); + mtp_client_->ReadFileChunkById( + storage_handle, file_id, offset, count, + base::Bind(&MediaTransferProtocolManagerImpl::OnReadFile, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnReadFileError, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual void GetFileInfoByPath(const std::string& storage_handle, + const std::string& path, + const GetFileInfoCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(MtpFileEntry(), true); + return; + } + get_file_info_callbacks_.push(callback); + mtp_client_->GetFileInfoByPath( + storage_handle, + path, + base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual void GetFileInfoById(const std::string& storage_handle, + uint32 file_id, + const GetFileInfoCallback& callback) OVERRIDE { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (!ContainsKey(handles_, storage_handle)) { + callback.Run(MtpFileEntry(), true); + return; + } + get_file_info_callbacks_.push(callback); + mtp_client_->GetFileInfoById( + storage_handle, + file_id, + base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfo, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&MediaTransferProtocolManagerImpl::OnGetFileInfoError, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + // Map of storage names to storage info. + typedef std::map<std::string, MtpStorageInfo> StorageInfoMap; + // Callback queues - DBus communication is in-order, thus callbacks are + // received in the same order as the requests. + typedef std::queue<OpenStorageCallback> OpenStorageCallbackQueue; + // (callback, handle) + typedef std::queue<std::pair<CloseStorageCallback, std::string> + > CloseStorageCallbackQueue; + typedef std::queue<ReadDirectoryCallback> ReadDirectoryCallbackQueue; + typedef std::queue<ReadFileCallback> ReadFileCallbackQueue; + typedef std::queue<GetFileInfoCallback> GetFileInfoCallbackQueue; + + void OnStorageChanged(bool is_attach, const std::string& storage_name) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (is_attach) { + mtp_client_->GetStorageInfo( + storage_name, + base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&base::DoNothing)); + return; + } + + // Detach case. + StorageInfoMap::iterator it = storage_info_map_.find(storage_name); + if (it == storage_info_map_.end()) { + // This might happen during initialization when |storage_info_map_| has + // not been fully populated yet? + return; + } + storage_info_map_.erase(it); + FOR_EACH_OBSERVER(Observer, + observers_, + StorageChanged(false /* detach */, storage_name)); + } + + void OnEnumerateStorages(const std::vector<std::string>& storage_names) { + for (size_t i = 0; i < storage_names.size(); ++i) { + mtp_client_->GetStorageInfo( + storage_names[i], + base::Bind(&MediaTransferProtocolManagerImpl::OnGetStorageInfo, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&base::DoNothing)); + } + } + + void OnGetStorageInfo(const MtpStorageInfo& storage_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + const std::string& storage_name = storage_info.storage_name(); + if (ContainsKey(storage_info_map_, storage_name)) { + // This should not happen, since MediaTransferProtocolManagerImpl should + // only call EnumerateStorages() once, which populates |storage_info_map_| + // with the already-attached devices. + // After that, all incoming signals are either for new storage + // attachments, which should not be in |storage_info_map_|, or for + // storage detachements, which do not add to |storage_info_map_|. + NOTREACHED(); + return; + } + + // New storage. Add it and let the observers know. + storage_info_map_.insert(std::make_pair(storage_name, storage_info)); + FOR_EACH_OBSERVER(Observer, + observers_, + StorageChanged(true /* is attach */, storage_name)); + } + + void OnOpenStorage(const std::string& handle) { + if (!ContainsKey(handles_, handle)) { + handles_.insert(handle); + open_storage_callbacks_.front().Run(handle, false); + } else { + NOTREACHED(); + open_storage_callbacks_.front().Run("", true); + } + open_storage_callbacks_.pop(); + } + + void OnOpenStorageError() { + open_storage_callbacks_.front().Run("", true); + open_storage_callbacks_.pop(); + } + + void OnCloseStorage() { + const std::string& handle = close_storage_callbacks_.front().second; + if (ContainsKey(handles_, handle)) { + handles_.erase(handle); + close_storage_callbacks_.front().first.Run(false); + } else { + NOTREACHED(); + close_storage_callbacks_.front().first.Run(true); + } + close_storage_callbacks_.pop(); + } + + void OnCloseStorageError() { + close_storage_callbacks_.front().first.Run(true); + close_storage_callbacks_.pop(); + } + + void OnReadDirectory(const std::vector<MtpFileEntry>& file_entries) { + read_directory_callbacks_.front().Run(file_entries, false); + read_directory_callbacks_.pop(); + } + + void OnReadDirectoryError() { + read_directory_callbacks_.front().Run(std::vector<MtpFileEntry>(), true); + read_directory_callbacks_.pop(); + } + + void OnReadFile(const std::string& data) { + read_file_callbacks_.front().Run(data, false); + read_file_callbacks_.pop(); + } + + void OnReadFileError() { + read_file_callbacks_.front().Run(std::string(), true); + read_file_callbacks_.pop(); + } + + void OnGetFileInfo(const MtpFileEntry& entry) { + get_file_info_callbacks_.front().Run(entry, false); + get_file_info_callbacks_.pop(); + } + + void OnGetFileInfoError() { + get_file_info_callbacks_.front().Run(MtpFileEntry(), true); + get_file_info_callbacks_.pop(); + } + + // Mtpd DBus client. + scoped_ptr<MediaTransferProtocolDaemonClient> mtp_client_; + +#if !defined(OS_CHROMEOS) + // And a D-Bus session for talking to mtpd. + scoped_refptr<dbus::Bus> session_bus_; +#endif + + // Device attachment / detachment observers. + ObserverList<Observer> observers_; + + base::WeakPtrFactory<MediaTransferProtocolManagerImpl> weak_ptr_factory_; + + // Everything below is only accessed on the UI thread. + + // Map to keep track of attached storages by name. + StorageInfoMap storage_info_map_; + + // Set of open storage handles. + std::set<std::string> handles_; + + // Queued callbacks. + OpenStorageCallbackQueue open_storage_callbacks_; + CloseStorageCallbackQueue close_storage_callbacks_; + ReadDirectoryCallbackQueue read_directory_callbacks_; + ReadFileCallbackQueue read_file_callbacks_; + GetFileInfoCallbackQueue get_file_info_callbacks_; + + DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolManagerImpl); +}; + +} // namespace + +// static +void MediaTransferProtocolManager::Initialize() { + if (g_media_transfer_protocol_manager) { + LOG(WARNING) << "MediaTransferProtocolManager was already initialized"; + return; + } + g_media_transfer_protocol_manager = new MediaTransferProtocolManagerImpl(); + VLOG(1) << "MediaTransferProtocolManager initialized"; +} + +// static +void MediaTransferProtocolManager::Shutdown() { + if (!g_media_transfer_protocol_manager) { + LOG(WARNING) << "MediaTransferProtocolManager::Shutdown() called with " + << "NULL manager"; + return; + } + delete g_media_transfer_protocol_manager; + g_media_transfer_protocol_manager = NULL; + VLOG(1) << "MediaTransferProtocolManager Shutdown completed"; +} + +// static +MediaTransferProtocolManager* MediaTransferProtocolManager::GetInstance() { + return g_media_transfer_protocol_manager; +} + +} // namespace device diff --git a/device/media_transfer_protocol/media_transfer_protocol_manager.h b/device/media_transfer_protocol/media_transfer_protocol_manager.h new file mode 100644 index 0000000..5c416b5 --- /dev/null +++ b/device/media_transfer_protocol/media_transfer_protocol_manager.h @@ -0,0 +1,143 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_MANAGER_H_ +#define DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_MANAGER_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "build/build_config.h" + +#if !defined(OS_LINUX) +#error "Only used on Linux and ChromeOS" +#endif + +class MtpFileEntry; +class MtpStorageInfo; + +namespace device { + +// This class handles the interaction with mtpd. +// Other classes can add themselves as observers. +class MediaTransferProtocolManager { + public: + // A callback to handle the result of OpenStorage. + // The first argument is the returned handle. + // The second argument is true if there was an error. + typedef base::Callback<void(const std::string& handle, + bool error)> OpenStorageCallback; + + // A callback to handle the result of CloseStorage. + // The argument is true if there was an error. + typedef base::Callback<void(bool error)> CloseStorageCallback; + + // A callback to handle the result of ReadDirectoryByPath/Id. + // The first argument is a vector of file entries. + // The second argument is true if there was an error. + typedef base::Callback<void(const std::vector<MtpFileEntry>& file_entries, + bool error)> ReadDirectoryCallback; + + // A callback to handle the result of ReadFileChunkByPath/Id. + // The first argument is a string containing the file data. + // The second argument is true if there was an error. + typedef base::Callback<void(const std::string& data, + bool error)> ReadFileCallback; + + // A callback to handle the result of GetFileInfoByPath/Id. + // The first argument is a file entry. + // The second argument is true if there was an error. + typedef base::Callback<void(const MtpFileEntry& file_entry, + bool error)> GetFileInfoCallback; + + // Implement this interface to be notified about MTP storage + // attachment / detachment events. + class Observer { + public: + virtual ~Observer() {} + + // A function called after a MTP storage has been attached / detached. + virtual void StorageChanged(bool is_attached, + const std::string& storage_name) = 0; + }; + + virtual ~MediaTransferProtocolManager() {} + + // Adds an observer. + virtual void AddObserver(Observer* observer) = 0; + + // Removes an observer. + virtual void RemoveObserver(Observer* observer) = 0; + + // Returns a vector of available MTP storages. + virtual const std::vector<std::string> GetStorages() const = 0; + + // On success, returns the the metadata for |storage_name|. + // Otherwise returns NULL. + virtual const MtpStorageInfo* GetStorageInfo( + const std::string& storage_name) const = 0; + + // Opens |storage_name| in |mode| and runs |callback|. + virtual void OpenStorage(const std::string& storage_name, + const std::string& mode, + const OpenStorageCallback& callback) = 0; + + // Close |storage_handle| and runs |callback|. + virtual void CloseStorage(const std::string& storage_handle, + const CloseStorageCallback& callback) = 0; + + // Reads directory entries from |path| on |storage_handle| and runs + // |callback|. + virtual void ReadDirectoryByPath(const std::string& storage_handle, + const std::string& path, + const ReadDirectoryCallback& callback) = 0; + + // Reads directory entries from |file_id| on |storage_handle| and runs + // |callback|. + virtual void ReadDirectoryById(const std::string& storage_handle, + uint32 file_id, + const ReadDirectoryCallback& callback) = 0; + + // Reads file data from |path| on |storage_handle| and runs |callback|. + // Reads |count| bytes of data starting at |offset|. + virtual void ReadFileChunkByPath(const std::string& storage_handle, + const std::string& path, + uint32 offset, + uint32 count, + const ReadFileCallback& callback) = 0; + + // Reads file data from |file_id| on |storage_handle| and runs |callback|. + // Reads |count| bytes of data starting at |offset|. + virtual void ReadFileChunkById(const std::string& storage_handle, + uint32 file_id, + uint32 offset, + uint32 count, + const ReadFileCallback& callback) = 0; + + // Gets the file metadata for |path| on |storage_handle| and runs |callback|. + virtual void GetFileInfoByPath(const std::string& storage_handle, + const std::string& path, + const GetFileInfoCallback& callback) = 0; + + // Gets the file metadata for |file_id| on |storage_handle| and runs + // |callback|. + virtual void GetFileInfoById(const std::string& storage_handle, + uint32 file_id, + const GetFileInfoCallback& callback) = 0; + + // Creates the global MediaTransferProtocolManager instance. + static void Initialize(); + + // Destroys the global MediaTransferProtocolManager instance if it exists. + static void Shutdown(); + + // Returns a pointer to the global MediaTransferProtocolManager instance. + // Initialize() should already have been called. + static MediaTransferProtocolManager* GetInstance(); +}; + +} // namespace device + +#endif // DEVICE_MEDIA_TRANSFER_PROTOCOL_MEDIA_TRANSFER_PROTOCOL_MANAGER_H_ |