Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Side by Side Diff: chrome/browser/extensions/api/document_scan/document_scan_api.cc

Issue 286933006: Implement a JavaScript API for document scanning (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: IDL indicates multiple images can be returned Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "chrome/browser/extensions/api/document_scan/document_scan_api.h"
6
7 #if defined(OS_CHROMEOS)
8 #include "base/task_runner_util.h"
9 #include "base/threading/worker_pool.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "chromeos/dbus/lorgnette_manager_client.h"
12 #include "chromeos/dbus/pipe_reader.h"
13 #endif // OS_CHROMEOS
14 #include "content/public/browser/browser_thread.h"
15 #include "extensions/browser/extension_system.h"
16 #if defined(OS_CHROMEOS)
17 #include "third_party/cros_system_api/dbus/service_constants.h"
18 #endif // OS_CHROMEOS
19
20 using content::BrowserThread;
21
22 namespace {
23
24 const char kImageScanFailedError[] = "Image scan failed";
25 const char kScannerImageMimeTypePng[] = "image/png";
26 const char kScanFunctionNotImplementedError[] = "Scan function not implemented";
27 const char kUserGestureRequiredError[] =
28 "User gesture required to perform scan";
29
30 } // namespace
31
32 namespace extensions {
33
34 namespace api {
35
36 #if defined(OS_CHROMEOS)
37 class DocumentScanInterfaceImpl : public DocumentScanInterface {
38 public:
39 DocumentScanInterfaceImpl() {}
40 virtual ~DocumentScanInterfaceImpl() {}
41
42 virtual void ListScanners(
43 const ListScannersResultsCallback& callback) OVERRIDE;
44 virtual void Scan(const std::string& scanner_name,
45 const document_scan::Scan::Params &params,
46 const ScanResultsCallback& callback) OVERRIDE;
47
48 private:
49 void OnScannerListReceived(
50 bool succeeded,
51 const chromeos::LorgnetteManagerClient::ScannerTable &scanners);
52 void OnScanCompleted(bool succeeded);
53 void OnScanDataCompleted();
54
55 ListScannersResultsCallback list_scanners_results_callback_;
56 ScanResultsCallback scan_results_callback_;
57 scoped_ptr<chromeos::PipeReaderForString> pipe_reader_;
58 std::string scanned_image_data_;
59
60 DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl);
61 };
62
63 void DocumentScanInterfaceImpl::ListScanners(
64 const ListScannersResultsCallback& callback) {
65 list_scannerrs_results_callback_ = callback;
66
67 chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient()->
68 ListScanners(base::Bind(
69 &DocumentScanInterfaceImpl::OnScannerListReceived,
70 base::Unretained(this)));
71 }
72
73 void DocumentScanInterfaceImpl::OnScannerListReceived(
74 bool succeeded,
75 const chromeos::LorgnetteManagerClient::ScannerTable &scanners) {
76 std::vector<ScannerDescription> scanner_descriptions;
77 for (chromeos::LorgnetteManagerClient::ScannerTable::const_iterator iter =
78 scanners.begin();
79 iter != scanners.end();
80 ++iter) {
81 ScannerDescription description;
82 description.name = iter->first;
83 const chromeos::LorgnetteManagerClient::ScannerTableEntry &entry =
84 iter->second;
85 chromeos::LorgnetteManagerClient::ScannerTableEntry::const_iterator info_it;
86 info_it = entry.find(lorgnette::kScannerPropertyManufacturer);
87 if (info_it != entry.end()) {
88 description->manufacturer = info_it->second;
89 }
90 info_it = entry.find(lorgnette::kScannerPropertyModel);
91 if (info_it != entry.end()) {
92 description->model = info_it->second;
93 }
94 info_it = entry.find(lorgnette::kScannerPropertyType);
95 if (info_it != entry.end()) {
96 description->scanner_type = info_it->second;
97 }
98 description->image_mime_type = kScannerImageMimeTypePng;
99 scanner_descriptions.push_back(info);
100 }
101 list_scanners_results_callback_.Run(scanner_descriptions, "");
102 }
103
104 void DocumentScanInterfaceImpl::Scan(
105 const std::string& scanner_name,
106 const document_scan::Scan::Params &params,
107 const ResultsCallback& callback) {
108 scan_results_callback_ = callback;
109
110 scoped_ptr<base::ListValue> empty_results(
111 document_scan::Scan::Results::Create(""));
112
113 VLOG(1) << "Choosing scanner " << scanner_name;
114 chromeos::LorgnetteManagerClient::ScanProperties properties;
115 switch (params.options.mode) {
116 case document_scan::SCAN_MODE_COLOR:
117 properties.mode = lorgnette::kScanPropertyModeColor;
118 break;
119
120 case document_scan::SCAN_MODE_GRAY:
121 properties.mode = lorgnette::kScanPropertyModeGray;
122 break;
123
124 case document_scan::SCAN_MODE_LINEART:
125 properties.mode = lorgnette::kScanPropertyModeLineart;
126 break;
127
128 default:
129 // Leave the mode parameter empty, thereby using the default.
130 break;
131 }
132
133 if (params.options.resolution_dpi.get()) {
134 properties.resolution_dpi = *params.options.resolution_dpi.get();
135 }
136
137 const bool kTasksAreSlow = true;
138 scoped_refptr<base::TaskRunner> task_runner =
139 base::WorkerPool::GetTaskRunner(kTasksAreSlow);
140
141 pipe_reader_.reset(new chromeos::PipeReaderForString(
142 task_runner,
143 base::Bind(&DocumentScanInterfaceImpl::OnScanDataCompleted,
144 base::Unretained(this))));
145 base::File file = pipe_reader_->StartIO();
146 base::PlatformFile platform_file = file.TakePlatformFile();
147 VLOG(1) << "ScanImage platform_file is " << platform_file;
148 chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient()->
149 ScanImage(scanner_name, platform_file, properties,
150 base::Bind(&DocumentScanInterfaceImpl::OnScanCompleted,
151 base::Unretained(this)));
152 }
153
154 void DocumentScanInterfaceImpl::OnScanCompleted(bool succeeded) {
155 VLOG(1) << "ScanImage returns " << succeeded;
156 if (pipe_reader_.get()) {
157 pipe_reader_->OnDataReady(-1); // terminate data stream
158 }
159
160 std::string error_string;
161 if (!succeeded) {
162 error_string = kImageScanFailedError;
163 }
164
165 scan_results_callback_.Run(
166 document_scan::Scan::Results::Create(
167 scanned_image_data_, kScannerImageMimeTypePng), error_string);
168 }
169
170 void DocumentScanInterfaceImpl::OnScanDataCompleted() {
171 pipe_reader_->GetData(&scanned_image_data_);
172 pipe_reader_.reset();
173 }
174
175 #else // OS_CHROMEOS
176 class DocumentScanInterfaceImpl : public DocumentScanInterface {
177 public:
178 DocumentScanInterfaceImpl() {}
179 virtual ~DocumentScanInterfaceImpl() {}
180
181 virtual void ListScanners(
182 const ListScannersResultsCallback& callback) OVERRIDE {
183 callback.Run(std::vector<ScannerDescription> (), "");
184 }
185 virtual void Scan(const std::string& scanner_name,
186 const document_scan::Scan::Params &params,
187 const ScanResultsCallback& callback) OVERRIDE {
188 callback.Run(document_scan::Scan::Results::Create(""),
189 kScanFunctionNotImplementedError);
190 }
191
192 private:
193 DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl);
194 };
195 #endif // OS_CHROMEOS
196
197 DocumentScanScanFunction::DocumentScanScanFunction()
198 : document_scan_interface_(new DocumentScanInterfaceImpl()) {}
199
200 DocumentScanScanFunction::~DocumentScanScanFunction() {}
201
202 bool DocumentScanScanFunction::Prepare() {
203 set_work_thread_id(BrowserThread::FILE);
204 params_ = document_scan::Scan::Params::Create(*args_);
205 EXTENSION_FUNCTION_VALIDATE(params_.get());
206 return true;
207 }
208
209 void DocumentScanScanFunction::AsyncWorkStart() {
210 if (!user_gesture()) {
211 error_ = kUserGestureRequiredError;
212 AsyncWorkCompleted();
213 return;
214 }
215
216 // Add a reference, which is balanced in OnScannerListReceived to keep the
217 // object around and allow the callback to be invoked.
218 AddRef();
219
220 document_scan_interface_->ListScanners(
221 base::Bind(&DocumentScanScanFunction::OnScannerListReceived,
222 base::Unretained(this)));
223 }
224
225 void DocumentScanScanFunction::OnScannerListReceived(
226 const std::vector<ScannerDescription>& scanner_descriptions,
227 const std::string& error) {
228 if (!scanner_descriptions.size()) {
229 results_ = document_scan::Scan::Results::Create(""));
230 error_ = kScannerNotAvailable;
231 AsyncWorkCompleted();
232
233 // Balance the AddRef in AsyncWorkStart().
234 Release();
235 return;
236 }
237
238 // TODO(pstew): Display a user interface for choosing a scanner.
239
240 document_scan_interface_->Scan(
241 scanner_descriptions[0].name,
242 *params_,
243 base::Bind(&DocumentScanScanFunction::OnResultsReceived,
244 base::Unretained(this)));
245 }
246
247 void DocumentScanScanFunction::OnResultsReceived(
248 scoped_ptr<base::ListValue> results, const std::string& error) {
249 // TODO(pstew): Display receied scan in the UI and confirm that this
250 // scan should be sent to the caller. If this is a multi-page scan,
251 // provide a means for adding additional scanned images up to the
252 // requested limit.
253 results_ = results.Pass();
254 error_ = error;
255 AsyncWorkCompleted();
256
257 // Balance the AddRef in AsyncWorkStart().
258 Release();
259 }
260
261 bool DocumentScanScanFunction::Respond() {
262 return error_.empty();
263 }
264
265 } // namespace api
266
267 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698