OLD | NEW |
---|---|
(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 #include <algorithm> | |
8 | |
9 #if defined(OS_CHROMEOS) | |
10 #include "base/task_runner_util.h" | |
11 #include "base/threading/worker_pool.h" | |
12 #include "chromeos/dbus/dbus_thread_manager.h" | |
13 #include "chromeos/dbus/lorgnette_manager_client.h" | |
14 #include "chromeos/dbus/pipe_reader.h" | |
15 #endif // OS_CHROMEOS | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "extensions/browser/extension_system.h" | |
18 #if defined(OS_CHROMEOS) | |
19 #include "third_party/cros_system_api/dbus/service_constants.h" | |
20 #endif // OS_CHROMEOS | |
21 | |
22 using content::BrowserThread; | |
23 using std::string; | |
24 using std::vector; | |
25 | |
26 namespace { | |
27 | |
28 const char kImageScanFailedError[] = "Image scan failed"; | |
29 const char kScannerImageMimeTypePng[] = "image/png"; | |
30 const char kScannerNotAvailable[] = "Scanner not available"; | |
31 const char kScanFunctionNotImplementedError[] = "Scan function not implemented"; | |
32 const char kUserGestureRequiredError[] = | |
33 "User gesture required to perform scan"; | |
34 const char kPngImageDataUrlPrefix[] = "data:image/png;base64,"; | |
35 } // namespace | |
36 | |
37 namespace extensions { | |
38 | |
39 namespace api { | |
40 | |
41 #if defined(OS_CHROMEOS) | |
mef
2014/10/13 15:59:54
Suggest: split into 3 files:
document_scan_interf
Paul Stewart
2014/10/14 19:28:31
Done, except for consistency sake with the generat
| |
42 class DocumentScanInterfaceImpl : public DocumentScanInterface { | |
43 public: | |
44 DocumentScanInterfaceImpl() {} | |
45 virtual ~DocumentScanInterfaceImpl() {} | |
46 | |
47 virtual void ListScanners( | |
48 const ListScannersResultsCallback& callback) OVERRIDE; | |
49 virtual void Scan(const string& scanner_name, | |
50 ScanMode mode, | |
51 int resolution_dpi, | |
52 const ScanResultsCallback& callback) OVERRIDE; | |
53 | |
54 private: | |
55 void OnScannerListReceived( | |
56 const ListScannersResultsCallback& callback, | |
57 bool succeeded, | |
58 const chromeos::LorgnetteManagerClient::ScannerTable &scanners); | |
59 void OnScanCompleted(const ScanResultsCallback &callback, bool succeeded); | |
60 void OnScanDataCompleted(); | |
61 string GetImageURL(string image_data); | |
62 | |
63 scoped_ptr<chromeos::PipeReaderForString> pipe_reader_; | |
64 string scanned_image_data_; | |
65 | |
66 DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl); | |
67 }; | |
68 | |
69 void DocumentScanInterfaceImpl::ListScanners( | |
70 const ListScannersResultsCallback& callback) { | |
71 chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient()-> | |
72 ListScanners(base::Bind( | |
73 &DocumentScanInterfaceImpl::OnScannerListReceived, | |
74 base::Unretained(this), | |
75 callback)); | |
76 } | |
77 | |
78 void DocumentScanInterfaceImpl::OnScannerListReceived( | |
79 const ListScannersResultsCallback& callback, | |
80 bool succeeded, | |
81 const chromeos::LorgnetteManagerClient::ScannerTable &scanners) { | |
82 vector<ScannerDescription> scanner_descriptions; | |
83 for (chromeos::LorgnetteManagerClient::ScannerTable::const_iterator iter = | |
84 scanners.begin(); | |
85 iter != scanners.end(); | |
86 ++iter) { | |
87 ScannerDescription description; | |
88 description.name = iter->first; | |
89 const chromeos::LorgnetteManagerClient::ScannerTableEntry &entry = | |
90 iter->second; | |
91 chromeos::LorgnetteManagerClient::ScannerTableEntry::const_iterator info_it; | |
92 info_it = entry.find(lorgnette::kScannerPropertyManufacturer); | |
93 if (info_it != entry.end()) { | |
94 description.manufacturer = info_it->second; | |
95 } | |
96 info_it = entry.find(lorgnette::kScannerPropertyModel); | |
97 if (info_it != entry.end()) { | |
98 description.model = info_it->second; | |
99 } | |
100 info_it = entry.find(lorgnette::kScannerPropertyType); | |
101 if (info_it != entry.end()) { | |
102 description.scanner_type = info_it->second; | |
103 } | |
104 description.image_mime_type = kScannerImageMimeTypePng; | |
105 scanner_descriptions.push_back(description); | |
106 } | |
107 callback.Run(scanner_descriptions, ""); | |
108 } | |
109 | |
110 void DocumentScanInterfaceImpl::Scan(const string& scanner_name, | |
111 ScanMode mode, | |
112 int resolution_dpi, | |
113 const ScanResultsCallback& callback) { | |
114 VLOG(1) << "Choosing scanner " << scanner_name; | |
115 chromeos::LorgnetteManagerClient::ScanProperties properties; | |
116 switch (mode) { | |
117 case kScanModeColor: | |
118 properties.mode = lorgnette::kScanPropertyModeColor; | |
119 break; | |
120 | |
121 case kScanModeGray: | |
122 properties.mode = lorgnette::kScanPropertyModeGray; | |
123 break; | |
124 | |
125 case kScanModeLineart: | |
126 properties.mode = lorgnette::kScanPropertyModeLineart; | |
127 break; | |
128 | |
129 default: | |
130 // Leave the mode parameter empty, thereby using the default. | |
131 break; | |
132 } | |
133 | |
134 if (resolution_dpi != 0) { | |
135 properties.resolution_dpi = resolution_dpi; | |
136 } | |
137 | |
138 const bool kTasksAreSlow = true; | |
139 scoped_refptr<base::TaskRunner> task_runner = | |
140 base::WorkerPool::GetTaskRunner(kTasksAreSlow); | |
141 | |
142 pipe_reader_.reset(new chromeos::PipeReaderForString( | |
143 task_runner, | |
144 base::Bind(&DocumentScanInterfaceImpl::OnScanDataCompleted, | |
145 base::Unretained(this)))); | |
146 base::File file = pipe_reader_->StartIO(); | |
147 base::PlatformFile platform_file = file.TakePlatformFile(); | |
148 VLOG(1) << "ScanImage platform_file is " << platform_file; | |
149 chromeos::DBusThreadManager::Get()->GetLorgnetteManagerClient()-> | |
150 ScanImage(scanner_name, platform_file, properties, | |
151 base::Bind(&DocumentScanInterfaceImpl::OnScanCompleted, | |
152 base::Unretained(this), | |
153 callback)); | |
154 } | |
155 | |
156 void DocumentScanInterfaceImpl::OnScanCompleted( | |
157 const ScanResultsCallback &callback, bool succeeded) { | |
158 VLOG(1) << "ScanImage returns " << succeeded; | |
159 if (pipe_reader_.get()) { | |
160 pipe_reader_->OnDataReady(-1); // terminate data stream | |
161 } | |
162 | |
163 string error_string; | |
164 if (!succeeded) { | |
165 error_string = kImageScanFailedError; | |
166 } | |
167 | |
168 vector<string> scanned_image_data_array; | |
169 scanned_image_data_array.push_back(GetImageURL(scanned_image_data_)); | |
170 callback.Run( | |
171 document_scan::Scan::Results::Create( | |
172 scanned_image_data_array, kScannerImageMimeTypePng), error_string); | |
173 } | |
174 | |
175 string DocumentScanInterfaceImpl::GetImageURL(string image_data) { | |
176 string image_data_base64; | |
177 base::Base64Encode(image_data, &image_data_base64); | |
178 return string(kPngImageDataUrlPrefix) + image_data_base64; | |
179 } | |
180 | |
181 void DocumentScanInterfaceImpl::OnScanDataCompleted() { | |
182 pipe_reader_->GetData(&scanned_image_data_); | |
183 pipe_reader_.reset(); | |
184 } | |
185 | |
186 #else // OS_CHROMEOS | |
187 class DocumentScanInterfaceImpl : public DocumentScanInterface { | |
mef
2014/10/13 15:59:54
If this is not implemented and not intended for im
Paul Stewart
2014/10/14 19:28:31
The intent is to make it possible to implement thi
| |
188 public: | |
189 DocumentScanInterfaceImpl() {} | |
190 virtual ~DocumentScanInterfaceImpl() {} | |
191 | |
192 virtual void ListScanners( | |
193 const ListScannersResultsCallback& callback) OVERRIDE { | |
194 callback.Run(vector<ScannerDescription> (), ""); | |
195 } | |
196 virtual void Scan(const string& scanner_name, | |
197 ScanMode mode, | |
198 int resolution_dpi, | |
199 const ScanResultsCallback& callback) OVERRIDE { | |
200 vector<string> null_scan_results; | |
201 callback.Run(document_scan::Scan::Results::Create(null_scan_results, ""), | |
202 kScanFunctionNotImplementedError); | |
203 } | |
204 | |
205 private: | |
206 DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl); | |
207 }; | |
208 #endif // OS_CHROMEOS | |
209 | |
210 DocumentScanScanFunction::DocumentScanScanFunction() | |
211 : document_scan_interface_(new DocumentScanInterfaceImpl()) {} | |
212 | |
213 DocumentScanScanFunction::~DocumentScanScanFunction() {} | |
214 | |
215 bool DocumentScanScanFunction::Prepare() { | |
216 set_work_thread_id(BrowserThread::FILE); | |
217 params_ = document_scan::Scan::Params::Create(*args_); | |
218 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
219 return true; | |
220 } | |
221 | |
222 void DocumentScanScanFunction::AsyncWorkStart() { | |
223 if (!user_gesture()) { | |
224 error_ = kUserGestureRequiredError; | |
225 AsyncWorkCompleted(); | |
226 return; | |
227 } | |
228 | |
229 // Add a reference, which is balanced in OnScannerListReceived to keep the | |
230 // object around and allow the callback to be invoked. | |
231 AddRef(); | |
232 | |
233 document_scan_interface_->ListScanners( | |
234 base::Bind(&DocumentScanScanFunction::OnScannerListReceived, | |
235 base::Unretained(this))); | |
236 } | |
237 | |
238 void DocumentScanScanFunction::OnScannerListReceived( | |
239 const vector<DocumentScanInterface::ScannerDescription>& | |
240 scanner_descriptions, | |
241 const string& error) { | |
242 vector<DocumentScanInterface::ScannerDescription>::const_iterator | |
243 scanner_i = scanner_descriptions.begin(); | |
244 if (params_->options.accepted_mime_types) { | |
245 vector<string>& accepted_types = | |
246 *params_->options.accepted_mime_types.get(); | |
247 for (; scanner_i != scanner_descriptions.end(); ++scanner_i) { | |
248 if (std::find(accepted_types.begin(), accepted_types.end(), | |
249 scanner_i->image_mime_type) != accepted_types.end()) { | |
250 break; | |
251 } | |
252 } | |
253 } | |
254 | |
255 if (scanner_i == scanner_descriptions.end()) { | |
256 vector<string> null_scan_results; | |
257 results_ = document_scan::Scan::Results::Create(null_scan_results, ""); | |
258 error_ = kScannerNotAvailable; | |
259 AsyncWorkCompleted(); | |
260 | |
261 // Balance the AddRef in AsyncWorkStart(). | |
262 Release(); | |
263 return; | |
264 } | |
265 | |
266 // TODO(pstew): Display a user interface for choosing a scanner. | |
267 // This is where the scan mode, DPI, etc, would be specified. | |
268 | |
269 document_scan_interface_->Scan( | |
270 scanner_i->name, | |
271 DocumentScanInterface::kScanModeColor, | |
272 0, | |
273 base::Bind(&DocumentScanScanFunction::OnResultsReceived, | |
274 base::Unretained(this))); | |
275 } | |
276 | |
277 void DocumentScanScanFunction::OnResultsReceived( | |
278 scoped_ptr<base::ListValue> results, const string& error) { | |
279 // TODO(pstew): Display receied scan in the UI and confirm that this | |
280 // scan should be sent to the caller. If this is a multi-page scan, | |
281 // provide a means for adding additional scanned images up to the | |
282 // requested limit. | |
283 results_ = results.Pass(); | |
284 error_ = error; | |
285 AsyncWorkCompleted(); | |
286 | |
287 // Balance the AddRef in AsyncWorkStart(). | |
288 Release(); | |
289 } | |
290 | |
291 bool DocumentScanScanFunction::Respond() { | |
292 return error_.empty(); | |
293 } | |
294 | |
295 } // namespace api | |
296 | |
297 } // namespace extensions | |
OLD | NEW |