Home | History | Annotate | Download | only in media_transfer_protocol
      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.
      4 
      5 #include "device/media_transfer_protocol/media_transfer_protocol_daemon_client.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/weak_ptr.h"
      9 #include "dbus/bus.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"
     16 
     17 namespace device {
     18 
     19 namespace {
     20 
     21 const char kInvalidResponseMsg[] = "Invalid Response: ";
     22 
     23 // The MediaTransferProtocolDaemonClient implementation.
     24 class MediaTransferProtocolDaemonClientImpl
     25     : public MediaTransferProtocolDaemonClient {
     26  public:
     27   explicit MediaTransferProtocolDaemonClientImpl(dbus::Bus* bus)
     28       : proxy_(bus->GetObjectProxy(
     29           mtpd::kMtpdServiceName,
     30           dbus::ObjectPath(mtpd::kMtpdServicePath))),
     31         weak_ptr_factory_(this) {
     32   }
     33 
     34   // MediaTransferProtocolDaemonClient override.
     35   virtual void EnumerateStorages(const EnumerateStoragesCallback& callback,
     36                                  const ErrorCallback& error_callback) OVERRIDE {
     37     dbus::MethodCall method_call(mtpd::kMtpdInterface,
     38                                  mtpd::kEnumerateStorages);
     39     proxy_->CallMethod(
     40         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     41         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnEnumerateStorages,
     42                    weak_ptr_factory_.GetWeakPtr(),
     43                    callback,
     44                    error_callback));
     45   }
     46 
     47   // MediaTransferProtocolDaemonClient override.
     48   virtual void GetStorageInfo(const std::string& storage_name,
     49                               const GetStorageInfoCallback& callback,
     50                               const ErrorCallback& error_callback) OVERRIDE {
     51     dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetStorageInfo);
     52     dbus::MessageWriter writer(&method_call);
     53     writer.AppendString(storage_name);
     54     proxy_->CallMethod(
     55         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     56         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetStorageInfo,
     57                    weak_ptr_factory_.GetWeakPtr(),
     58                    storage_name,
     59                    callback,
     60                    error_callback));
     61   }
     62 
     63   // MediaTransferProtocolDaemonClient override.
     64   virtual void OpenStorage(const std::string& storage_name,
     65                            const std::string& mode,
     66                            const OpenStorageCallback& callback,
     67                            const ErrorCallback& error_callback) OVERRIDE {
     68     dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kOpenStorage);
     69     dbus::MessageWriter writer(&method_call);
     70     writer.AppendString(storage_name);
     71     DCHECK_EQ(mtpd::kReadOnlyMode, mode);
     72     writer.AppendString(mtpd::kReadOnlyMode);
     73     proxy_->CallMethod(
     74         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     75         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnOpenStorage,
     76                    weak_ptr_factory_.GetWeakPtr(),
     77                    callback,
     78                    error_callback));
     79   }
     80 
     81   // MediaTransferProtocolDaemonClient override.
     82   virtual void CloseStorage(const std::string& handle,
     83                             const CloseStorageCallback& callback,
     84                             const ErrorCallback& error_callback) OVERRIDE {
     85     dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kCloseStorage);
     86     dbus::MessageWriter writer(&method_call);
     87     writer.AppendString(handle);
     88     proxy_->CallMethod(
     89         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     90         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnCloseStorage,
     91                    weak_ptr_factory_.GetWeakPtr(),
     92                    callback,
     93                    error_callback));
     94   }
     95 
     96   // MediaTransferProtocolDaemonClient override.
     97   virtual void ReadDirectoryByPath(
     98       const std::string& handle,
     99       const std::string& path,
    100       const ReadDirectoryCallback& callback,
    101       const ErrorCallback& error_callback) OVERRIDE {
    102     dbus::MethodCall method_call(mtpd::kMtpdInterface,
    103                                  mtpd::kReadDirectoryByPath);
    104     dbus::MessageWriter writer(&method_call);
    105     writer.AppendString(handle);
    106     writer.AppendString(path);
    107     proxy_->CallMethod(
    108         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    109         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory,
    110                    weak_ptr_factory_.GetWeakPtr(),
    111                    callback,
    112                    error_callback));
    113   }
    114 
    115   // MediaTransferProtocolDaemonClient override.
    116   virtual void ReadDirectoryById(
    117       const std::string& handle,
    118       uint32 file_id,
    119       const ReadDirectoryCallback& callback,
    120       const ErrorCallback& error_callback) OVERRIDE {
    121     dbus::MethodCall method_call(mtpd::kMtpdInterface,
    122                                  mtpd::kReadDirectoryById);
    123     dbus::MessageWriter writer(&method_call);
    124     writer.AppendString(handle);
    125     writer.AppendUint32(file_id);
    126     proxy_->CallMethod(
    127         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    128         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadDirectory,
    129                    weak_ptr_factory_.GetWeakPtr(),
    130                    callback,
    131                    error_callback));
    132   }
    133 
    134   // MediaTransferProtocolDaemonClient override.
    135   virtual void ReadFileChunkByPath(
    136       const std::string& handle,
    137       const std::string& path,
    138       uint32 offset,
    139       uint32 bytes_to_read,
    140       const ReadFileCallback& callback,
    141       const ErrorCallback& error_callback) OVERRIDE {
    142     dbus::MethodCall method_call(mtpd::kMtpdInterface,
    143                                  mtpd::kReadFileChunkByPath);
    144     dbus::MessageWriter writer(&method_call);
    145     writer.AppendString(handle);
    146     writer.AppendString(path);
    147     writer.AppendUint32(offset);
    148     writer.AppendUint32(bytes_to_read);
    149     proxy_->CallMethod(
    150         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    151         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
    152                    weak_ptr_factory_.GetWeakPtr(),
    153                    callback,
    154                    error_callback));
    155   }
    156 
    157   // MediaTransferProtocolDaemonClient override.
    158   virtual void ReadFileChunkById(const std::string& handle,
    159                                  uint32 file_id,
    160                                  uint32 offset,
    161                                  uint32 bytes_to_read,
    162                                  const ReadFileCallback& callback,
    163                                  const ErrorCallback& error_callback) OVERRIDE {
    164     dbus::MethodCall method_call(mtpd::kMtpdInterface,
    165                                  mtpd::kReadFileChunkById);
    166     dbus::MessageWriter writer(&method_call);
    167     writer.AppendString(handle);
    168     writer.AppendUint32(file_id);
    169     writer.AppendUint32(offset);
    170     writer.AppendUint32(bytes_to_read);
    171     proxy_->CallMethod(
    172         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    173         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnReadFile,
    174                    weak_ptr_factory_.GetWeakPtr(),
    175                    callback,
    176                    error_callback));
    177   }
    178 
    179   // MediaTransferProtocolDaemonClient override.
    180   virtual void GetFileInfoByPath(const std::string& handle,
    181                                  const std::string& path,
    182                                  const GetFileInfoCallback& callback,
    183                                  const ErrorCallback& error_callback) OVERRIDE {
    184     dbus::MethodCall method_call(mtpd::kMtpdInterface,
    185                                  mtpd::kGetFileInfoByPath);
    186     dbus::MessageWriter writer(&method_call);
    187     writer.AppendString(handle);
    188     writer.AppendString(path);
    189     proxy_->CallMethod(
    190         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    191         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo,
    192                    weak_ptr_factory_.GetWeakPtr(),
    193                    callback,
    194                    error_callback));
    195   }
    196 
    197   // MediaTransferProtocolDaemonClient override.
    198   virtual void GetFileInfoById(const std::string& handle,
    199                                uint32 file_id,
    200                                const GetFileInfoCallback& callback,
    201                                const ErrorCallback& error_callback) OVERRIDE {
    202     dbus::MethodCall method_call(mtpd::kMtpdInterface, mtpd::kGetFileInfoById);
    203     dbus::MessageWriter writer(&method_call);
    204     writer.AppendString(handle);
    205     writer.AppendUint32(file_id);
    206     proxy_->CallMethod(
    207         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    208         base::Bind(&MediaTransferProtocolDaemonClientImpl::OnGetFileInfo,
    209                    weak_ptr_factory_.GetWeakPtr(),
    210                    callback,
    211                    error_callback));
    212   }
    213 
    214   // MediaTransferProtocolDaemonClient override.
    215   virtual void SetUpConnections(
    216       const MTPStorageEventHandler& handler) OVERRIDE {
    217     static const SignalEventTuple kSignalEventTuples[] = {
    218       { mtpd::kMTPStorageAttached, true },
    219       { mtpd::kMTPStorageDetached, false },
    220     };
    221     const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
    222 
    223     for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
    224       proxy_->ConnectToSignal(
    225           mtpd::kMtpdInterface,
    226           kSignalEventTuples[i].signal_name,
    227           base::Bind(&MediaTransferProtocolDaemonClientImpl::OnMTPStorageSignal,
    228                      weak_ptr_factory_.GetWeakPtr(),
    229                      handler,
    230                      kSignalEventTuples[i].is_attach),
    231           base::Bind(&MediaTransferProtocolDaemonClientImpl::OnSignalConnected,
    232                      weak_ptr_factory_.GetWeakPtr()));
    233     }
    234   }
    235 
    236  private:
    237   // A struct to contain a pair of signal name and attachment event type.
    238   // Used by SetUpConnections.
    239   struct SignalEventTuple {
    240     const char *signal_name;
    241     bool is_attach;
    242   };
    243 
    244   // Handles the result of EnumerateStorages and calls |callback| or
    245   // |error_callback|.
    246   void OnEnumerateStorages(const EnumerateStoragesCallback& callback,
    247                            const ErrorCallback& error_callback,
    248                            dbus::Response* response) {
    249     if (!response) {
    250       error_callback.Run();
    251       return;
    252     }
    253     dbus::MessageReader reader(response);
    254     std::vector<std::string> storage_names;
    255     if (!reader.PopArrayOfStrings(&storage_names)) {
    256       LOG(ERROR) << kInvalidResponseMsg << response->ToString();
    257       error_callback.Run();
    258       return;
    259     }
    260     callback.Run(storage_names);
    261   }
    262 
    263   // Handles the result of GetStorageInfo and calls |callback| or
    264   // |error_callback|.
    265   void OnGetStorageInfo(const std::string& storage_name,
    266                         const GetStorageInfoCallback& callback,
    267                         const ErrorCallback& error_callback,
    268                         dbus::Response* response) {
    269     if (!response) {
    270       error_callback.Run();
    271       return;
    272     }
    273 
    274     dbus::MessageReader reader(response);
    275     MtpStorageInfo protobuf;
    276     if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
    277       LOG(ERROR) << kInvalidResponseMsg << response->ToString();
    278       error_callback.Run();
    279       return;
    280     }
    281     callback.Run(protobuf);
    282   }
    283 
    284   // Handles the result of OpenStorage and calls |callback| or |error_callback|.
    285   void OnOpenStorage(const OpenStorageCallback& callback,
    286                      const ErrorCallback& error_callback,
    287                      dbus::Response* response) {
    288     if (!response) {
    289       error_callback.Run();
    290       return;
    291     }
    292     dbus::MessageReader reader(response);
    293     std::string handle;
    294     if (!reader.PopString(&handle)) {
    295       LOG(ERROR) << kInvalidResponseMsg << response->ToString();
    296       error_callback.Run();
    297       return;
    298     }
    299     callback.Run(handle);
    300   }
    301 
    302   // Handles the result of CloseStorage and calls |callback| or
    303   // |error_callback|.
    304   void OnCloseStorage(const CloseStorageCallback& callback,
    305                       const ErrorCallback& error_callback,
    306                       dbus::Response* response) {
    307     if (!response) {
    308       error_callback.Run();
    309       return;
    310     }
    311     callback.Run();
    312   }
    313 
    314   // Handles the result of ReadDirectoryByPath/Id and calls |callback| or
    315   // |error_callback|.
    316   void OnReadDirectory(const ReadDirectoryCallback& callback,
    317                        const ErrorCallback& error_callback,
    318                        dbus::Response* response) {
    319     if (!response) {
    320       error_callback.Run();
    321       return;
    322     }
    323 
    324     std::vector<MtpFileEntry> file_entries;
    325     dbus::MessageReader reader(response);
    326     MtpFileEntries entries_protobuf;
    327     if (!reader.PopArrayOfBytesAsProto(&entries_protobuf)) {
    328       LOG(ERROR) << kInvalidResponseMsg << response->ToString();
    329       error_callback.Run();
    330       return;
    331     }
    332 
    333     for (int i = 0; i < entries_protobuf.file_entries_size(); ++i)
    334       file_entries.push_back(entries_protobuf.file_entries(i));
    335     callback.Run(file_entries);
    336   }
    337 
    338   // Handles the result of ReadFileChunkByPath/Id and calls |callback| or
    339   // |error_callback|.
    340   void OnReadFile(const ReadFileCallback& callback,
    341                   const ErrorCallback& error_callback,
    342                   dbus::Response* response) {
    343     if (!response) {
    344       error_callback.Run();
    345       return;
    346     }
    347 
    348     uint8* data_bytes = NULL;
    349     size_t data_length = 0;
    350     dbus::MessageReader reader(response);
    351     if (!reader.PopArrayOfBytes(&data_bytes, &data_length)) {
    352       error_callback.Run();
    353       return;
    354     }
    355     std::string data(reinterpret_cast<const char*>(data_bytes), data_length);
    356     callback.Run(data);
    357   }
    358 
    359   // Handles the result of GetFileInfoByPath/Id and calls |callback| or
    360   // |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;
    367     }
    368 
    369     dbus::MessageReader reader(response);
    370     MtpFileEntry protobuf;
    371     if (!reader.PopArrayOfBytesAsProto(&protobuf)) {
    372       LOG(ERROR) << kInvalidResponseMsg << response->ToString();
    373       error_callback.Run();
    374       return;
    375     }
    376     callback.Run(protobuf);
    377   }
    378 
    379   // Handles MTPStorageAttached/Dettached signals and calls |handler|.
    380   void OnMTPStorageSignal(MTPStorageEventHandler handler,
    381                           bool is_attach,
    382                           dbus::Signal* signal) {
    383     dbus::MessageReader reader(signal);
    384     std::string storage_name;
    385     if (!reader.PopString(&storage_name)) {
    386       LOG(ERROR) << "Invalid signal: " << signal->ToString();
    387       return;
    388     }
    389     DCHECK(!storage_name.empty());
    390     handler.Run(is_attach, storage_name);
    391   }
    392 
    393 
    394   // Handles the result of signal connection setup.
    395   void OnSignalConnected(const std::string& interface,
    396                          const std::string& signal,
    397                          bool succeeded) {
    398     LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
    399                               << signal << " failed.";
    400   }
    401 
    402   dbus::ObjectProxy* proxy_;
    403 
    404   // Note: This should remain the last member so it'll be destroyed and
    405   // invalidate its weak pointers before any other members are destroyed.
    406   base::WeakPtrFactory<MediaTransferProtocolDaemonClientImpl> weak_ptr_factory_;
    407 
    408   DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientImpl);
    409 };
    410 
    411 // A stub implementaion of MediaTransferProtocolDaemonClient.
    412 class MediaTransferProtocolDaemonClientStubImpl
    413     : public MediaTransferProtocolDaemonClient {
    414  public:
    415   MediaTransferProtocolDaemonClientStubImpl() {}
    416   virtual ~MediaTransferProtocolDaemonClientStubImpl() {}
    417 
    418   virtual void EnumerateStorages(
    419       const EnumerateStoragesCallback& callback,
    420       const ErrorCallback& error_callback) OVERRIDE {}
    421   virtual void GetStorageInfo(
    422       const std::string& storage_name,
    423       const GetStorageInfoCallback& callback,
    424       const ErrorCallback& error_callback) OVERRIDE {}
    425   virtual void OpenStorage(const std::string& storage_name,
    426                            const std::string& mode,
    427                            const OpenStorageCallback& callback,
    428                            const ErrorCallback& error_callback) OVERRIDE {}
    429   virtual void CloseStorage(const std::string& handle,
    430                             const CloseStorageCallback& callback,
    431                             const ErrorCallback& error_callback) OVERRIDE {}
    432   virtual void ReadDirectoryByPath(
    433       const std::string& handle,
    434       const std::string& path,
    435       const ReadDirectoryCallback& callback,
    436       const ErrorCallback& error_callback) OVERRIDE {}
    437   virtual void ReadDirectoryById(
    438       const std::string& handle,
    439       uint32 file_id,
    440       const ReadDirectoryCallback& callback,
    441       const ErrorCallback& error_callback) OVERRIDE {}
    442   virtual void ReadFileChunkByPath(
    443       const std::string& handle,
    444       const std::string& path,
    445       uint32 offset,
    446       uint32 length,
    447       const ReadFileCallback& callback,
    448       const ErrorCallback& error_callback) OVERRIDE {}
    449   virtual void ReadFileChunkById(
    450       const std::string& handle,
    451       uint32 file_id,
    452       uint32 offset,
    453       uint32 length,
    454       const ReadFileCallback& callback,
    455       const ErrorCallback& error_callback) OVERRIDE {}
    456   virtual void GetFileInfoByPath(
    457       const std::string& handle,
    458       const std::string& path,
    459       const GetFileInfoCallback& callback,
    460       const ErrorCallback& error_callback) OVERRIDE {}
    461   virtual void GetFileInfoById(const std::string& handle,
    462                                uint32 file_id,
    463                                const GetFileInfoCallback& callback,
    464                                const ErrorCallback& error_callback) OVERRIDE {}
    465   virtual void SetUpConnections(
    466       const MTPStorageEventHandler& handler) OVERRIDE {}
    467 
    468  private:
    469   DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDaemonClientStubImpl);
    470 };
    471 
    472 }  // namespace
    473 
    474 ////////////////////////////////////////////////////////////////////////////////
    475 // MediaTransferProtocolDaemonClient
    476 
    477 MediaTransferProtocolDaemonClient::MediaTransferProtocolDaemonClient() {}
    478 
    479 MediaTransferProtocolDaemonClient::~MediaTransferProtocolDaemonClient() {}
    480 
    481 // static
    482 MediaTransferProtocolDaemonClient*
    483 MediaTransferProtocolDaemonClient::Create(dbus::Bus* bus, bool is_stub) {
    484   if (is_stub)
    485     return new MediaTransferProtocolDaemonClientStubImpl();
    486   return new MediaTransferProtocolDaemonClientImpl(bus);
    487 }
    488 
    489 }  // namespace device
    490