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