Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / lorgnette_manager_client.cc
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/memory/scoped_ptr.h"
15 #include "base/task_runner_util.h"
16 #include "base/threading/worker_pool.h"
17 #include "chromeos/dbus/pipe_reader.h"
18 #include "dbus/bus.h"
19 #include "dbus/message.h"
20 #include "dbus/object_path.h"
21 #include "dbus/object_proxy.h"
22 #include "net/base/file_stream.h"
23 #include "third_party/cros_system_api/dbus/service_constants.h"
24
25 namespace chromeos {
26
27 // The LorgnetteManagerClient implementation used in production.
28 class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
29  public:
30   LorgnetteManagerClientImpl() :
31       lorgnette_daemon_proxy_(NULL), weak_ptr_factory_(this) {}
32
33   virtual ~LorgnetteManagerClientImpl() {}
34
35   void ListScanners(const ListScannersCallback& callback) override {
36     dbus::MethodCall method_call(lorgnette::kManagerServiceInterface,
37                                  lorgnette::kListScannersMethod);
38     lorgnette_daemon_proxy_->CallMethod(
39         &method_call,
40         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
41         base::Bind(&LorgnetteManagerClientImpl::OnListScanners,
42                    weak_ptr_factory_.GetWeakPtr(),
43                    callback));
44   }
45
46   // LorgnetteManagerClient override.
47   void ScanImageToFile(
48       std::string device_name,
49       const ScanProperties& properties,
50       const ScanImageToFileCallback& callback,
51       base::File* file) override {
52     dbus::FileDescriptor* file_descriptor = new dbus::FileDescriptor();
53     file_descriptor->PutValue(file->TakePlatformFile());
54     // Punt descriptor validity check to a worker thread; on return we'll
55     // issue the D-Bus request to stop tracing and collect results.
56     base::WorkerPool::PostTaskAndReply(
57         FROM_HERE,
58         base::Bind(&LorgnetteManagerClientImpl::CheckValidity,
59                    file_descriptor),
60         base::Bind(&LorgnetteManagerClientImpl::OnCheckValidityScanImage,
61                    weak_ptr_factory_.GetWeakPtr(),
62                    base::Owned(file_descriptor),
63                    device_name,
64                    properties,
65                    callback),
66         false);
67   }
68
69   void ScanImageToString(
70       std::string device_name,
71       const ScanProperties& properties,
72       const ScanImageToStringCallback& callback) override {
73     // Owned by the callback created in scan_to_string_completion->Start().
74     ScanToStringCompletion* scan_to_string_completion =
75         new ScanToStringCompletion();
76     base::File file;
77     ScanImageToFileCallback file_callback =
78         scan_to_string_completion->Start(callback, &file);
79     ScanImageToFile(device_name, properties, file_callback, &file);
80   }
81
82  protected:
83   void Init(dbus::Bus* bus) override {
84     lorgnette_daemon_proxy_ =
85         bus->GetObjectProxy(lorgnette::kManagerServiceName,
86                             dbus::ObjectPath(lorgnette::kManagerServicePath));
87   }
88
89  private:
90   class ScanToStringCompletion {
91    public:
92     ScanToStringCompletion() {}
93     virtual ~ScanToStringCompletion() {}
94
95     // Creates a file stream in |file| that will stream image data to
96     // a string that will be supplied to |callback|.  Passes ownership
97     // of |this| to a returned callback that can be handed to a
98     // ScanImageToFile invocation.
99     ScanImageToFileCallback Start(const ScanImageToStringCallback& callback,
100                                   base::File *file) {
101       CHECK(!pipe_reader_.get());
102       const bool kTasksAreSlow = true;
103       scoped_refptr<base::TaskRunner> task_runner =
104           base::WorkerPool::GetTaskRunner(kTasksAreSlow);
105       pipe_reader_.reset(
106           new chromeos::PipeReaderForString(
107               task_runner,
108               base::Bind(&ScanToStringCompletion::OnScanToStringDataCompleted,
109                        base::Unretained(this))));
110       *file = pipe_reader_->StartIO();
111
112       return base::Bind(&ScanToStringCompletion::OnScanToStringCompleted,
113                         base::Owned(this), callback);
114     }
115
116    private:
117     // Called when a |pipe_reader_| completes reading scan data to a string.
118     void OnScanToStringDataCompleted() {
119       pipe_reader_->GetData(&scanned_image_data_string_);
120       pipe_reader_.reset();
121     }
122
123     // Called by LorgnetteManagerImpl when scan completes.
124     void OnScanToStringCompleted(const ScanImageToStringCallback& callback,
125                                  bool succeeded) {
126       if (pipe_reader_.get()) {
127         pipe_reader_->OnDataReady(-1);  // terminate data stream
128       }
129       callback.Run(succeeded, scanned_image_data_string_);
130       scanned_image_data_string_.clear();
131     }
132
133     scoped_ptr<chromeos::PipeReaderForString> pipe_reader_;
134     std::string scanned_image_data_string_;
135
136     DISALLOW_COPY_AND_ASSIGN(ScanToStringCompletion);
137   };
138
139   // Called when ListScanners completes.
140   void OnListScanners(const ListScannersCallback& callback,
141                       dbus::Response* response) {
142     ScannerTable scanners;
143     dbus::MessageReader table_reader(NULL);
144     if (!response || !dbus::MessageReader(response).PopArray(&table_reader)) {
145       callback.Run(false, scanners);
146       return;
147     }
148
149     bool decode_failure = false;
150     while (table_reader.HasMoreData()) {
151       std::string device_name;
152       dbus::MessageReader device_entry_reader(NULL);
153       dbus::MessageReader device_element_reader(NULL);
154       if (!table_reader.PopDictEntry(&device_entry_reader) ||
155           !device_entry_reader.PopString(&device_name) ||
156           !device_entry_reader.PopArray(&device_element_reader)) {
157         decode_failure = true;
158         break;
159       }
160
161       ScannerTableEntry scanner_entry;
162       while (device_element_reader.HasMoreData()) {
163         dbus::MessageReader device_attribute_reader(NULL);
164         std::string attribute;
165         std::string value;
166         if (!device_element_reader.PopDictEntry(&device_attribute_reader) ||
167             !device_attribute_reader.PopString(&attribute) ||
168             !device_attribute_reader.PopString(&value)) {
169           decode_failure = true;
170           break;
171         }
172         scanner_entry[attribute] = value;
173       }
174
175       if (decode_failure)
176           break;
177
178       scanners[device_name] = scanner_entry;
179     }
180
181     if (decode_failure) {
182       LOG(ERROR) << "Failed to decode response from ListScanners";
183       callback.Run(false, scanners);
184     } else {
185       callback.Run(true, scanners);
186     }
187   }
188
189   // Called to check descriptor validity on a thread where i/o is permitted.
190   static void CheckValidity(dbus::FileDescriptor* file_descriptor) {
191     file_descriptor->CheckValidity();
192   }
193
194   // Called when a CheckValidity response is received.
195   void OnCheckValidityScanImage(
196       dbus::FileDescriptor* file_descriptor,
197       std::string device_name,
198       const ScanProperties& properties,
199       const ScanImageToFileCallback& callback) {
200     if (!file_descriptor->is_valid()) {
201       LOG(ERROR) << "Failed to scan image: file descriptor is invalid";
202       callback.Run(false);
203       return;
204     }
205     // Issue the dbus request to scan an image.
206     dbus::MethodCall method_call(
207         lorgnette::kManagerServiceInterface,
208         lorgnette::kScanImageMethod);
209     dbus::MessageWriter writer(&method_call);
210     writer.AppendString(device_name);
211     writer.AppendFileDescriptor(*file_descriptor);
212
213     dbus::MessageWriter option_writer(NULL);
214     dbus::MessageWriter element_writer(NULL);
215     writer.OpenArray("{sv}", &option_writer);
216     if (!properties.mode.empty()) {
217       option_writer.OpenDictEntry(&element_writer);
218       element_writer.AppendString(lorgnette::kScanPropertyMode);
219       element_writer.AppendVariantOfString(properties.mode);
220       option_writer.CloseContainer(&element_writer);
221     }
222     if (properties.resolution_dpi) {
223       option_writer.OpenDictEntry(&element_writer);
224       element_writer.AppendString(lorgnette::kScanPropertyResolution);
225       element_writer.AppendVariantOfUint32(properties.resolution_dpi);
226       option_writer.CloseContainer(&element_writer);
227     }
228     writer.CloseContainer(&option_writer);
229
230     lorgnette_daemon_proxy_->CallMethod(
231         &method_call,
232         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
233         base::Bind(&LorgnetteManagerClientImpl::OnScanImageComplete,
234                    weak_ptr_factory_.GetWeakPtr(),
235                    callback));
236   }
237
238   // Called when a response for ScanImage() is received.
239   void OnScanImageComplete(const ScanImageToFileCallback& callback,
240                            dbus::Response* response) {
241     if (!response) {
242       LOG(ERROR) << "Failed to scan image";
243       callback.Run(false);
244       return;
245     }
246     callback.Run(true);
247   }
248
249   dbus::ObjectProxy* lorgnette_daemon_proxy_;
250   base::WeakPtrFactory<LorgnetteManagerClientImpl> weak_ptr_factory_;
251
252   DISALLOW_COPY_AND_ASSIGN(LorgnetteManagerClientImpl);
253 };
254
255 LorgnetteManagerClient::LorgnetteManagerClient() {
256 }
257
258 LorgnetteManagerClient::~LorgnetteManagerClient() {
259 }
260
261 // static
262 LorgnetteManagerClient* LorgnetteManagerClient::Create() {
263   return new LorgnetteManagerClientImpl();
264 }
265
266 }  // namespace chromeos