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/platform_file.h"
15 #include "base/threading/worker_pool.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"
25 // The LorgnetteManagerClient implementation used in production.
26 class LorgnetteManagerClientImpl
: public LorgnetteManagerClient
{
28 LorgnetteManagerClientImpl() :
29 lorgnette_daemon_proxy_(NULL
), weak_ptr_factory_(this) {}
31 virtual ~LorgnetteManagerClientImpl() {}
33 virtual void ListScanners(const ListScannersCallback
& callback
) OVERRIDE
{
34 dbus::MethodCall
method_call(lorgnette::kManagerServiceInterface
,
35 lorgnette::kListScannersMethod
);
36 lorgnette_daemon_proxy_
->CallMethod(
38 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
39 base::Bind(&LorgnetteManagerClientImpl::OnListScanners
,
40 weak_ptr_factory_
.GetWeakPtr(),
44 // LorgnetteManagerClient override.
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(
55 base::Bind(&LorgnetteManagerClientImpl::CheckValidity
,
57 base::Bind(&LorgnetteManagerClientImpl::OnCheckValidityScanImage
,
58 weak_ptr_factory_
.GetWeakPtr(),
59 base::Owned(file_descriptor
),
67 virtual void Init(dbus::Bus
* bus
) OVERRIDE
{
68 lorgnette_daemon_proxy_
=
69 bus
->GetObjectProxy(lorgnette::kManagerServiceName
,
70 dbus::ObjectPath(lorgnette::kManagerServicePath
));
74 // Called when ListScanners completes.
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
);
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;
96 ScannerTableEntry scanner_entry
;
97 while (device_element_reader
.HasMoreData()) {
98 dbus::MessageReader
device_attribute_reader(NULL
);
99 std::string attribute
;
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;
107 scanner_entry
[attribute
] = value
;
113 scanners
[device_name
] = scanner_entry
;
116 if (decode_failure
) {
117 LOG(ERROR
) << "Failed to decode response from ListScanners";
118 callback
.Run(false, scanners
);
120 callback
.Run(true, scanners
);
124 // Called to check descriptor validity on a thread where i/o is permitted.
125 static void CheckValidity(dbus::FileDescriptor
* file_descriptor
) {
126 file_descriptor
->CheckValidity();
129 // Called when a CheckValidity response is received.
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";
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
);
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
);
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
);
163 writer
.CloseContainer(&option_writer
);
165 lorgnette_daemon_proxy_
->CallMethod(
167 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
168 base::Bind(&LorgnetteManagerClientImpl::OnScanImageComplete
,
169 weak_ptr_factory_
.GetWeakPtr(),
173 // Called when a response for ScanImage() is received.
174 void OnScanImageComplete(const ScanImageCallback
& callback
,
175 dbus::Response
* response
) {
177 LOG(ERROR
) << "Failed to scan image";
184 dbus::ObjectProxy
* lorgnette_daemon_proxy_
;
185 base::WeakPtrFactory
<LorgnetteManagerClientImpl
> weak_ptr_factory_
;
187 DISALLOW_COPY_AND_ASSIGN(LorgnetteManagerClientImpl
);
190 LorgnetteManagerClient::LorgnetteManagerClient() {
193 LorgnetteManagerClient::~LorgnetteManagerClient() {
197 LorgnetteManagerClient
* LorgnetteManagerClient::Create() {
198 return new LorgnetteManagerClientImpl();
201 } // namespace chromeos