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.
5 #include "chromeos/dbus/lorgnette_manager_client.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"
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"
24 // The LorgnetteManagerClient implementation used in production.
25 class LorgnetteManagerClientImpl
: public LorgnetteManagerClient
{
27 LorgnetteManagerClientImpl() :
28 lorgnette_daemon_proxy_(NULL
), weak_ptr_factory_(this) {}
30 virtual ~LorgnetteManagerClientImpl() {}
32 virtual void ListScanners(const ListScannersCallback
& callback
) OVERRIDE
{
33 dbus::MethodCall
method_call(lorgnette::kManagerServiceInterface
,
34 lorgnette::kListScannersMethod
);
35 lorgnette_daemon_proxy_
->CallMethod(
37 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
38 base::Bind(&LorgnetteManagerClientImpl::OnListScanners
,
39 weak_ptr_factory_
.GetWeakPtr(),
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(
54 base::Bind(&LorgnetteManagerClientImpl::CheckValidity
,
56 base::Bind(&LorgnetteManagerClientImpl::OnCheckValidityScanImage
,
57 weak_ptr_factory_
.GetWeakPtr(),
58 base::Owned(file_descriptor
),
66 virtual void Init(dbus::Bus
* bus
) OVERRIDE
{
67 lorgnette_daemon_proxy_
=
68 bus
->GetObjectProxy(lorgnette::kManagerServiceName
,
69 dbus::ObjectPath(lorgnette::kManagerServicePath
));
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
);
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;
95 ScannerTableEntry scanner_entry
;
96 while (device_element_reader
.HasMoreData()) {
97 dbus::MessageReader
device_attribute_reader(NULL
);
98 std::string attribute
;
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;
106 scanner_entry
[attribute
] = value
;
112 scanners
[device_name
] = scanner_entry
;
115 if (decode_failure
) {
116 LOG(ERROR
) << "Failed to decode response from ListScanners";
117 callback
.Run(false, scanners
);
119 callback
.Run(true, scanners
);
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();
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";
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
);
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
);
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
);
162 writer
.CloseContainer(&option_writer
);
164 lorgnette_daemon_proxy_
->CallMethod(
166 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
167 base::Bind(&LorgnetteManagerClientImpl::OnScanImageComplete
,
168 weak_ptr_factory_
.GetWeakPtr(),
172 // Called when a response for ScanImage() is received.
173 void OnScanImageComplete(const ScanImageCallback
& callback
,
174 dbus::Response
* response
) {
176 LOG(ERROR
) << "Failed to scan image";
183 dbus::ObjectProxy
* lorgnette_daemon_proxy_
;
184 base::WeakPtrFactory
<LorgnetteManagerClientImpl
> weak_ptr_factory_
;
186 DISALLOW_COPY_AND_ASSIGN(LorgnetteManagerClientImpl
);
189 LorgnetteManagerClient::LorgnetteManagerClient() {
192 LorgnetteManagerClient::~LorgnetteManagerClient() {
196 LorgnetteManagerClient
* LorgnetteManagerClient::Create() {
197 return new LorgnetteManagerClientImpl();
200 } // namespace chromeos