Upstream version 9.38.198.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/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