Home | History | Annotate | Download | only in dbus
      1 // Copyright 2014 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 "chromeos/dbus/lorgnette_manager_client.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/callback.h"
     12 #include "base/location.h"
     13 #include "base/memory/ref_counted_memory.h"
     14 #include "base/threading/worker_pool.h"
     15 #include "dbus/bus.h"
     16 #include "dbus/message.h"
     17 #include "dbus/object_path.h"
     18 #include "dbus/object_proxy.h"
     19 #include "net/base/file_stream.h"
     20 #include "third_party/cros_system_api/dbus/service_constants.h"
     21 
     22 namespace chromeos {
     23 
     24 // The LorgnetteManagerClient implementation used in production.
     25 class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
     26  public:
     27   LorgnetteManagerClientImpl() :
     28       lorgnette_daemon_proxy_(NULL), weak_ptr_factory_(this) {}
     29 
     30   virtual ~LorgnetteManagerClientImpl() {}
     31 
     32   virtual void ListScanners(const ListScannersCallback& callback) OVERRIDE {
     33     dbus::MethodCall method_call(lorgnette::kManagerServiceInterface,
     34                                  lorgnette::kListScannersMethod);
     35     lorgnette_daemon_proxy_->CallMethod(
     36         &method_call,
     37         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     38         base::Bind(&LorgnetteManagerClientImpl::OnListScanners,
     39                    weak_ptr_factory_.GetWeakPtr(),
     40                    callback));
     41   }
     42 
     43   // LorgnetteManagerClient override.
     44   virtual void ScanImage(std::string device_name,
     45                          base::PlatformFile file,
     46                          const ScanProperties& properties,
     47                          const ScanImageCallback& callback) OVERRIDE {
     48     dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor();
     49     file_descriptor->PutValue(file);
     50     // Punt descriptor validity check to a worker thread; on return we'll
     51     // issue the D-Bus request to stop tracing and collect results.
     52     base::WorkerPool::PostTaskAndReply(
     53         FROM_HERE,
     54         base::Bind(&LorgnetteManagerClientImpl::CheckValidity,
     55                    file_descriptor),
     56         base::Bind(&LorgnetteManagerClientImpl::OnCheckValidityScanImage,
     57                    weak_ptr_factory_.GetWeakPtr(),
     58                    base::Owned(file_descriptor),
     59                    device_name,
     60                    properties,
     61                    callback),
     62         false);
     63   }
     64 
     65  protected:
     66   virtual void Init(dbus::Bus* bus) OVERRIDE {
     67     lorgnette_daemon_proxy_ =
     68         bus->GetObjectProxy(lorgnette::kManagerServiceName,
     69                             dbus::ObjectPath(lorgnette::kManagerServicePath));
     70   }
     71 
     72  private:
     73   // Called when ListScanners completes.
     74   void OnListScanners(const ListScannersCallback& callback,
     75                       dbus::Response* response) {
     76     ScannerTable scanners;
     77     dbus::MessageReader table_reader(NULL);
     78     if (!response || !dbus::MessageReader(response).PopArray(&table_reader)) {
     79       callback.Run(false, scanners);
     80       return;
     81     }
     82 
     83     bool decode_failure = false;
     84     while (table_reader.HasMoreData()) {
     85       std::string device_name;
     86       dbus::MessageReader device_entry_reader(NULL);
     87       dbus::MessageReader device_element_reader(NULL);
     88       if (!table_reader.PopDictEntry(&device_entry_reader) ||
     89           !device_entry_reader.PopString(&device_name) ||
     90           !device_entry_reader.PopArray(&device_element_reader)) {
     91         decode_failure = true;
     92         break;
     93       }
     94 
     95       ScannerTableEntry scanner_entry;
     96       while (device_element_reader.HasMoreData()) {
     97         dbus::MessageReader device_attribute_reader(NULL);
     98         std::string attribute;
     99         std::string value;
    100         if (!device_element_reader.PopDictEntry(&device_attribute_reader) ||
    101             !device_attribute_reader.PopString(&attribute) ||
    102             !device_attribute_reader.PopString(&value)) {
    103           decode_failure = true;
    104           break;
    105         }
    106         scanner_entry[attribute] = value;
    107       }
    108 
    109       if (decode_failure)
    110           break;
    111 
    112       scanners[device_name] = scanner_entry;
    113     }
    114 
    115     if (decode_failure) {
    116       LOG(ERROR) << "Failed to decode response from ListScanners";
    117       callback.Run(false, scanners);
    118     } else {
    119       callback.Run(true, scanners);
    120     }
    121   }
    122 
    123   // Called to check descriptor validity on a thread where i/o is permitted.
    124   static void CheckValidity(dbus::FileDescriptor* file_descriptor) {
    125     file_descriptor->CheckValidity();
    126   }
    127 
    128   // Called when a CheckValidity response is received.
    129   void OnCheckValidityScanImage(
    130       dbus::FileDescriptor* file_descriptor,
    131       std::string device_name,
    132       const ScanProperties& properties,
    133       const ScanImageCallback& callback) {
    134     if (!file_descriptor->is_valid()) {
    135       LOG(ERROR) << "Failed to scan image: file descriptor is invalid";
    136       callback.Run(false);
    137       return;
    138     }
    139     // Issue the dbus request to scan an image.
    140     dbus::MethodCall method_call(
    141         lorgnette::kManagerServiceInterface,
    142         lorgnette::kScanImageMethod);
    143     dbus::MessageWriter writer(&method_call);
    144     writer.AppendString(device_name);
    145     writer.AppendFileDescriptor(*file_descriptor);
    146 
    147     dbus::MessageWriter option_writer(NULL);
    148     dbus::MessageWriter element_writer(NULL);
    149     writer.OpenArray("{sv}", &option_writer);
    150     if (!properties.mode.empty()) {
    151       option_writer.OpenDictEntry(&element_writer);
    152       element_writer.AppendString(lorgnette::kScanPropertyMode);
    153       element_writer.AppendVariantOfString(properties.mode);
    154       option_writer.CloseContainer(&element_writer);
    155     }
    156     if (properties.resolution_dpi) {
    157       option_writer.OpenDictEntry(&element_writer);
    158       element_writer.AppendString(lorgnette::kScanPropertyResolution);
    159       element_writer.AppendVariantOfUint32(properties.resolution_dpi);
    160       option_writer.CloseContainer(&element_writer);
    161     }
    162     writer.CloseContainer(&option_writer);
    163 
    164     lorgnette_daemon_proxy_->CallMethod(
    165         &method_call,
    166         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    167         base::Bind(&LorgnetteManagerClientImpl::OnScanImageComplete,
    168                    weak_ptr_factory_.GetWeakPtr(),
    169                    callback));
    170   }
    171 
    172   // Called when a response for ScanImage() is received.
    173   void OnScanImageComplete(const ScanImageCallback& callback,
    174                            dbus::Response* response) {
    175     if (!response) {
    176       LOG(ERROR) << "Failed to scan image";
    177       callback.Run(false);
    178       return;
    179     }
    180     callback.Run(true);
    181   }
    182 
    183   dbus::ObjectProxy* lorgnette_daemon_proxy_;
    184   base::WeakPtrFactory<LorgnetteManagerClientImpl> weak_ptr_factory_;
    185 
    186   DISALLOW_COPY_AND_ASSIGN(LorgnetteManagerClientImpl);
    187 };
    188 
    189 LorgnetteManagerClient::LorgnetteManagerClient() {
    190 }
    191 
    192 LorgnetteManagerClient::~LorgnetteManagerClient() {
    193 }
    194 
    195 // static
    196 LorgnetteManagerClient* LorgnetteManagerClient::Create() {
    197   return new LorgnetteManagerClientImpl();
    198 }
    199 
    200 }  // namespace chromeos
    201